Skip to content

Commit c541716

Browse files
bioxzCalcProgrammer1
authored andcommitted
Add support for SteelSeries Apex 9
1 parent 70f3ae1 commit c541716

7 files changed

Lines changed: 370 additions & 7 deletions

File tree

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*---------------------------------------------------------*\
2+
| SteelSeriesApex9Controller.cpp |
3+
| |
4+
| Driver for SteelSeries Apex 9 |
5+
| |
6+
| This file is part of the OpenRGB project |
7+
| SPDX-License-Identifier: GPL-2.0-only |
8+
\*---------------------------------------------------------*/
9+
10+
#include <cstring>
11+
#include "SteelSeriesApex9Controller.h"
12+
13+
using namespace std::chrono_literals;
14+
15+
static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
16+
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //20
17+
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
18+
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //40
19+
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
20+
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, //60
21+
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
22+
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x64, 0xE0, //80
23+
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xF0, 0x31, 0x87,
24+
0x88, 0x89, 0x8A, 0x8B, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, //100
25+
0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
26+
0x63 };
27+
28+
SteelSeriesApex9Controller::SteelSeriesApex9Controller(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController (dev_handle, path, dev_name)
29+
{
30+
proto_type = type;
31+
}
32+
33+
SteelSeriesApex9Controller::~SteelSeriesApex9Controller()
34+
{
35+
hid_close(dev);
36+
}
37+
38+
void SteelSeriesApex9Controller::SetMode(unsigned char mode /*mode*/, std::vector<RGBColor> /*colors*/ )
39+
{
40+
unsigned char mode_colors[9];
41+
42+
active_mode = mode;
43+
44+
memset(mode_colors, 0x00, sizeof(mode_colors));
45+
}
46+
47+
void SteelSeriesApex9Controller::SetLEDsDirect(std::vector<RGBColor> colors)
48+
{
49+
unsigned char buf[APEX_9_PACKET_LENGTH];
50+
int num_keys = 0;
51+
52+
num_keys = sizeof(keys) / sizeof(*keys);
53+
54+
/*-----------------------------------------------------*\
55+
| Zero out buffer |
56+
\*-----------------------------------------------------*/
57+
memset(buf, 0x00, sizeof(buf));
58+
59+
/*-----------------------------------------------------*\
60+
| Set up Direct packet |
61+
\*-----------------------------------------------------*/
62+
buf[0x00] = 0;
63+
buf[0x01] = APEX_9_PACKET_ID_DIRECT;
64+
buf[0x02] = num_keys;
65+
66+
/*-----------------------------------------------------*\
67+
| Fill in color data |
68+
\*-----------------------------------------------------*/
69+
for(int i = 0; i < num_keys; i++)
70+
{
71+
buf[(i*4)+3] = keys[i];
72+
buf[(i*4)+4] = RGBGetRValue(colors[i]);
73+
buf[(i*4)+5] = RGBGetGValue(colors[i]);
74+
buf[(i*4)+6] = RGBGetBValue(colors[i]);
75+
}
76+
77+
/*-----------------------------------------------------*\
78+
| Send packet |
79+
\*-----------------------------------------------------*/
80+
hid_send_feature_report(dev, buf, APEX_9_PACKET_LENGTH);
81+
82+
}
83+
84+
std::string SteelSeriesApex9Controller::GetSerial()
85+
{
86+
std::string return_string = "";
87+
88+
switch(proto_type)
89+
{
90+
case APEX_9_TKL:
91+
return_string = "64847";
92+
break;
93+
case APEX_9_MINI:
94+
return_string = "64837";
95+
break;
96+
default:
97+
return_string = "Apex 9 GetSerial() error";
98+
}
99+
100+
return(return_string);
101+
}
102+
103+
std::string SteelSeriesApex9Controller::GetVersion()
104+
{
105+
std::string return_string = "Unsupported protocol";
106+
107+
unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE];
108+
unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE];
109+
int result;
110+
111+
memset(obuf, 0x00, sizeof(obuf));
112+
obuf[0x00] = 0;
113+
obuf[0x01] = 0x90;
114+
hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE);
115+
result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2);
116+
117+
if(result > 0)
118+
{
119+
std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE);
120+
fwver = fwver.substr(2, fwver.size());
121+
fwver = fwver.c_str();
122+
123+
/*---------------------------------------------*\
124+
| Find 2 periods in string, if found we can |
125+
| form a X.Y.Z revision. |
126+
\*---------------------------------------------*/
127+
std::size_t majorp = fwver.find('.');
128+
if(majorp != std::string::npos)
129+
{
130+
std::size_t minorp = fwver.find('.', majorp+1);
131+
if(minorp != std::string::npos)
132+
{
133+
std::string major = fwver.substr(0, majorp);
134+
std::string minor = fwver.substr(majorp+1, (minorp-majorp-1));
135+
std::string build = fwver.substr(minorp+1);
136+
return_string = "KBD: " + major + "." + minor + "." + build;
137+
}
138+
}
139+
}
140+
141+
return(return_string);
142+
}
143+
144+
/*-------------------------------------------------------------------------------------------------*\
145+
| Private packet sending functions. |
146+
\*-------------------------------------------------------------------------------------------------*/
147+
148+
void SteelSeriesApex9Controller::SelectProfile(unsigned char profile)
149+
{
150+
unsigned char buf[65];
151+
152+
/*-----------------------------------------------------*\
153+
| Zero out buffer, set up packet and send |
154+
\*-----------------------------------------------------*/
155+
memset(buf, 0x00, sizeof(buf));
156+
buf[0x00] = 0;
157+
buf[0x01] = 0x89;
158+
buf[0x02] = profile;
159+
hid_send_feature_report(dev, buf, 65);
160+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*---------------------------------------------------------*\
2+
| SteelSeriesApex9Controller.h |
3+
| |
4+
| Driver for SteelSeries Apex 9 |
5+
| |
6+
| This file is part of the OpenRGB project |
7+
| SPDX-License-Identifier: GPL-2.0-only |
8+
\*---------------------------------------------------------*/
9+
10+
#pragma once
11+
12+
#include <string>
13+
#include <hidapi.h>
14+
#include "RGBController.h"
15+
#include "SteelSeriesGeneric.h"
16+
#include "SteelSeriesApexBaseController.h"
17+
18+
enum
19+
{
20+
APEX_9_PACKET_ID_DIRECT = 0x40, /* Direct mode */
21+
APEX_9_PACKET_LENGTH = 513,
22+
};
23+
24+
class SteelSeriesApex9Controller : public SteelSeriesApexBaseController
25+
{
26+
public:
27+
SteelSeriesApex9Controller(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name);
28+
~SteelSeriesApex9Controller();
29+
30+
void SetMode(unsigned char mode, std::vector<RGBColor> colors);
31+
void SetLEDsDirect(std::vector<RGBColor> colors);
32+
33+
std::string GetSerial() override;
34+
std::string GetVersion() override;
35+
36+
private:
37+
void SelectProfile(unsigned char profile);
38+
};

Controllers/SteelSeriesController/SteelSeriesApexBaseController.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ class SteelSeriesApexBaseController
2727

2828
std::string GetLocation();
2929
std::string GetName();
30-
std::string GetSerial();
31-
std::string GetVersion();
30+
virtual std::string GetSerial();
31+
virtual std::string GetVersion();
3232

3333
virtual void SetMode(unsigned char mode, std::vector<RGBColor> colors) = 0;
3434

Controllers/SteelSeriesController/SteelSeriesApexController/RGBController_SteelSeriesApex.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void RGBController_SteelSeriesApex::SetupZones()
106106
new_zone.matrix_map = new matrix_map_type;
107107
new_zone.matrix_map->map = (unsigned int *) malloc(matrix_mapsize*sizeof(unsigned int));
108108

109-
if((proto_type == APEX) || (proto_type == APEX_M))
109+
if((proto_type == APEX) || (proto_type == APEX_M) || (proto_type == APEX_9_TKL) || (proto_type == APEX_9_MINI))
110110
{
111111
SetSkuRegion(*new_zone.matrix_map, sku);
112112
}
@@ -116,7 +116,7 @@ void RGBController_SteelSeriesApex::SetupZones()
116116
new_zone.matrix_map = NULL;
117117
}
118118

119-
if((proto_type == APEX) || (proto_type == APEX_M))
119+
if((proto_type == APEX) || (proto_type == APEX_M) || (proto_type == APEX_9_TKL) || (proto_type == APEX_9_MINI))
120120
{
121121
new_zone.leds_min = zone_sizes[zone_idx];
122122
new_zone.leds_max = zone_sizes[zone_idx];

0 commit comments

Comments
 (0)