Skip to content

Commit c13f031

Browse files
filipesnCalcProgrammer1
authored andcommitted
Fix support for SteelSeries Apex Pro TKL 2023
1 parent 5a484a0 commit c13f031

3 files changed

Lines changed: 145 additions & 8 deletions

File tree

Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.cpp

Lines changed: 123 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
/*---------------------------------------------------------*\
22
| SteelSeriesApexController.cpp |
33
| |
4-
| Driver for SteelSeries Apex 7 |
4+
| Driver for SteelSeries Apex Keyboards |
5+
| |
6+
| New driver based on SignalRGB Plugins |
7+
| https://gitlab.com/signalrgb/signal-plugins/ |
58
| |
69
| Eric Samuelson (edbgon) 05 Jul 2020 |
10+
| Filipe S. (filipesn) 5 Jan 2026 |
711
| |
812
| This file is part of the OpenRGB project |
913
| SPDX-License-Identifier: GPL-2.0-or-later |
1014
\*---------------------------------------------------------*/
1115

1216
#include <cstring>
17+
#include <cstdio>
1318
#include "SteelSeriesApexController.h"
19+
#include "LogManager.h"
1420

1521
using namespace std::chrono_literals;
1622

23+
#define FIRMWARE_REQ_LEN 645
24+
1725
static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
1826
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //20
1927
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
@@ -29,7 +37,10 @@ static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x
2937

3038
SteelSeriesApexController::SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController(dev_handle, path, dev_name)
3139
{
32-
proto_type = type;
40+
proto_type = type;
41+
use_new_protocol = false;
42+
43+
SendInitialization();
3344
}
3445

3546
SteelSeriesApexController::~SteelSeriesApexController()
@@ -55,8 +66,23 @@ void SteelSeriesApexController::SetLEDsDirect(std::vector<RGBColor> colors)
5566
unsigned char buf[643];
5667
int num_keys = 0;
5768

69+
unsigned char packet_id = APEX_PACKET_ID_DIRECT;
70+
5871
num_keys = sizeof(keys) / sizeof(*keys);
5972

73+
if(use_new_protocol)
74+
{
75+
struct hid_device_info* info = hid_get_device_info(dev);
76+
if(info && (info->product_id == 0x162C || info->product_id == 0x162D)) // Aparently Gen 3 wireless models reuse this protocol, make sure to place their PID here and further below when developing.
77+
{
78+
packet_id = APEX_2023_PACKET_ID_DIRECT_WIRELESS;
79+
}
80+
else
81+
{
82+
packet_id = APEX_2023_PACKET_ID_DIRECT;
83+
}
84+
}
85+
6086
/*-----------------------------------------------------*\
6187
| Zero out buffer |
6288
\*-----------------------------------------------------*/
@@ -66,8 +92,8 @@ void SteelSeriesApexController::SetLEDsDirect(std::vector<RGBColor> colors)
6692
| Set up Direct packet |
6793
\*-----------------------------------------------------*/
6894
buf[0x00] = 0;
69-
buf[0x01] = APEX_PACKET_ID_DIRECT;
70-
buf[0x02] = num_keys;
95+
buf[0x01] = packet_id;
96+
buf[0x02] = (use_new_protocol) ? (unsigned char)colors.size() : num_keys;
7197

7298
/*-----------------------------------------------------*\
7399
| Fill in color data |
@@ -106,3 +132,96 @@ void SteelSeriesApexController::SelectProfile
106132
buf[0x02] = profile;
107133
hid_send_feature_report(dev, buf, 65);
108134
}
135+
136+
void SteelSeriesApexController::SendInitialization()
137+
{
138+
unsigned char buf[FIRMWARE_REQ_LEN];
139+
unsigned char read_buf[65];
140+
int res = 0;
141+
char version_str[32] = "Unknown";
142+
143+
struct hid_device_info* info = hid_get_device_info(dev);
144+
unsigned short pid = (info) ? info->product_id : 0;
145+
146+
// Firmware check
147+
if(pid == 0x1628)
148+
{
149+
/*-----------------------------------------------------*\
150+
| Zero out buffer |
151+
\*-----------------------------------------------------*/
152+
memset(buf, 0x00, sizeof(buf));
153+
buf[0x00] = 0x00;
154+
buf[0x01] = 0x90;
155+
156+
/*-----------------------------------------------------*\
157+
| Send packet |
158+
\*-----------------------------------------------------*/
159+
hid_write(dev, buf, 65);
160+
161+
/*-----------------------------------------------------*\
162+
| Read Response |
163+
\*-----------------------------------------------------*/
164+
memset(read_buf, 0x00, sizeof(read_buf));
165+
res = hid_read_timeout(dev, read_buf, sizeof(read_buf), 200);
166+
167+
/*-----------------------------------------------------*\
168+
| Firmware Check |
169+
\*-----------------------------------------------------*/
170+
if(res > 2 && read_buf[0] == 0x90)
171+
{
172+
int major = 0, minor = 0, patch = 0;
173+
char* fw_ptr = (char*)&read_buf[2];
174+
175+
snprintf(version_str, sizeof(version_str), "%s", fw_ptr);
176+
177+
int count = sscanf(version_str, "%d.%d.%d", &major, &minor, &patch);
178+
179+
if(count == 3)
180+
{
181+
// Currently set to 1.19.7 or newer.
182+
if(major > 1)
183+
{
184+
use_new_protocol = true;
185+
}
186+
else if(major == 1)
187+
{
188+
if(minor > 19)
189+
{
190+
use_new_protocol = true;
191+
}
192+
else if(minor == 19 && patch >= 7)
193+
{
194+
use_new_protocol = true;
195+
}
196+
}
197+
}
198+
}
199+
}
200+
// // Aparently Gen 3 models reuse this protocol, make sure to place their PID here and further above for wireless when developing.
201+
else if(pid == 0x162C || pid == 0x162D)
202+
{
203+
use_new_protocol = true;
204+
}
205+
206+
/*-----------------------------------------------------*\
207+
| Send Initialization packet on new protocol. |
208+
\*-----------------------------------------------------*/
209+
if(use_new_protocol)
210+
{
211+
memset(buf, 0x00, sizeof(buf));
212+
buf[0x00] = 0x00;
213+
buf[0x01] = APEX_2023_PACKET_ID_INIT;
214+
hid_send_feature_report(dev, buf, APEX_2023_PACKET_LENGTH);
215+
216+
LOG_DEBUG("[%s] Using Apex 2023 protocol. FW: %s", name.c_str(), version_str);
217+
}
218+
else
219+
{
220+
LOG_DEBUG("[%s] Using Apex Legacy protocol. FW: %s", name.c_str(), version_str);
221+
}
222+
}
223+
224+
std::string SteelSeriesApexController::GetSerial()
225+
{
226+
return "64865";
227+
}

Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
/*---------------------------------------------------------*\
2-
| SteelSeriesApexController.h |
2+
| SteelSeriesApexController.cpp |
33
| |
4-
| Driver for SteelSeries Apex 7 |
4+
| Driver for SteelSeries Apex Keyboards |
5+
| |
6+
| New driver based on SignalRGB Plugins |
7+
| https://gitlab.com/signalrgb/signal-plugins/ |
58
| |
69
| Eric Samuelson (edbgon) 05 Jul 2020 |
10+
| Filipe S. (filipesn) 5 Jan 2026 |
711
| |
812
| This file is part of the OpenRGB project |
913
| SPDX-License-Identifier: GPL-2.0-or-later |
@@ -19,7 +23,11 @@
1923

2024
enum
2125
{
22-
APEX_PACKET_ID_DIRECT = 0x3a, /* Direct mode */
26+
APEX_PACKET_ID_DIRECT = 0x3a, /* Direct mode */
27+
APEX_2023_PACKET_ID_DIRECT = 0x40, /* New Wired Direct mode */
28+
APEX_2023_PACKET_ID_DIRECT_WIRELESS = 0x61, /* New Wireless Direct mode */
29+
APEX_2023_PACKET_ID_INIT = 0x4B, /* New Initialization */
30+
APEX_2023_PACKET_LENGTH = 643,
2331
};
2432

2533
class SteelSeriesApexController : public SteelSeriesApexBaseController
@@ -36,10 +44,16 @@ class SteelSeriesApexController : public SteelSeriesApexBaseController
3644

3745
void SetLEDsDirect(std::vector<RGBColor> colors);
3846

47+
std::string GetSerial() override;
48+
3949
private:
4050

4151
void SelectProfile
4252
(
4353
unsigned char profile
4454
);
55+
56+
void SendInitialization();
57+
58+
bool use_new_protocol;
4559
};

Controllers/SteelSeriesController/SteelSeriesControllerDetect.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@
116116
#define STEELSERIES_APEX_PRO_PID 0x1610
117117
#define STEELSERIES_APEX_PRO_TKL_PID 0x1614
118118
#define STEELSERIES_APEX_PRO_TKL_2023_PID 0x1628
119+
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1 0x1630
120+
#define STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2 0x1632
119121
#define STEELSERIES_APEX_M750_PID 0x0616
120122
#define STEELSERIES_APEX_OG_PID 0x1202
121123
#define STEELSERIES_APEX_350_PID 0x1206
@@ -504,7 +506,9 @@ REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 TKL", Dete
504506
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 9 Mini", DetectSteelSeriesApex9Mini, STEELSERIES_VID, STEELSERIES_APEX_9_MINI_PID, 1 );
505507
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_PID, 1 );
506508
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_PID, 1 );
507-
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL 2023", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_PID, 1 );
509+
REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL 2023 Wired", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_PID, 1 );
510+
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL 2023 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_WL_PID_1, 3, 0xFFC0, 1);
511+
REGISTER_HID_DETECTOR_IPU("SteelSeries Apex Pro TKL 2023 Wireless", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_WL_PID_2, 3, 0xFFC0, 1);
508512
REGISTER_HID_DETECTOR_I ("SteelSeries Apex M750", DetectSteelSeriesApexM, STEELSERIES_VID, STEELSERIES_APEX_M750_PID, 2 );
509513
REGISTER_HID_DETECTOR_I ("SteelSeries Apex (OG)/Apex Fnatic", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_OG_PID, 0 );
510514
REGISTER_HID_DETECTOR_I ("SteelSeries Apex 350", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_350_PID, 0 );

0 commit comments

Comments
 (0)