Skip to content

Commit fe11115

Browse files
Jeff PCalcProgrammer1
authored andcommitted
Add support for Corsair Commander Core / Elite Capellix
Amended for code style by Adam Honse <[email protected]>
1 parent 9a00f1d commit fe11115

File tree

6 files changed

+546
-0
lines changed

6 files changed

+546
-0
lines changed
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
/*---------------------------------------------------------*\
2+
| CorsairCommanderCoreController.cpp |
3+
| |
4+
| Processing Code for Corsair Commander Core |
5+
| |
6+
| Jeff P. |
7+
\*---------------------------------------------------------*/
8+
9+
#include "CorsairCommanderCoreController.h"
10+
11+
#include <cstring>
12+
#include <iomanip>
13+
#include <iostream>
14+
15+
using namespace std::chrono_literals;
16+
17+
CorsairCommanderCoreController::CorsairCommanderCoreController(hid_device* dev_handle, const char* path)
18+
{
19+
dev = dev_handle;
20+
location = path;
21+
keepalive_thread_run = 1;
22+
controller_ready = 0;
23+
24+
/*-----------------------------------------------------*\
25+
| Initialize controller |
26+
\*-----------------------------------------------------*/
27+
InitController();
28+
29+
/*-----------------------------------------------------*\
30+
| Start keepalive thread |
31+
\*-----------------------------------------------------*/
32+
keepalive_thread = new std::thread(&CorsairCommanderCoreController::KeepaliveThread, this);
33+
}
34+
35+
CorsairCommanderCoreController::~CorsairCommanderCoreController()
36+
{
37+
/*-----------------------------------------------------*\
38+
| Close keepalive thread |
39+
\*-----------------------------------------------------*/
40+
keepalive_thread_run = 0;
41+
keepalive_thread->join();
42+
delete keepalive_thread;
43+
44+
/*-----------------------------------------------------*\
45+
| Close HID device |
46+
\*-----------------------------------------------------*/
47+
hid_close(dev);
48+
}
49+
50+
void CorsairCommanderCoreController::InitController()
51+
{
52+
/*-----------------------------------------------------*\
53+
| Packet sequence to put controller into direct mode |
54+
\*-----------------------------------------------------*/
55+
unsigned char buffarray[][5] =
56+
{
57+
{0x08, 0x01, 0x03, 0x00, 0x02},
58+
{0x08, 0x0D, 0x00, 0x22, 0x00},
59+
};
60+
61+
SendMultiPkt(buffarray, sizeof(buffarray) / sizeof(buffarray[0]), sizeof(buffarray)[0] / sizeof(buffarray[0][0]));
62+
SetFanMode();
63+
}
64+
65+
std::string CorsairCommanderCoreController::GetLocationString()
66+
{
67+
return("HID: " + location);
68+
}
69+
70+
void CorsairCommanderCoreController::KeepaliveThread()
71+
{
72+
while(keepalive_thread_run.load())
73+
{
74+
if (controller_ready)
75+
{
76+
if((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::seconds(10))
77+
{
78+
SendCommit();
79+
}
80+
}
81+
std::this_thread::sleep_for(1s);
82+
}
83+
}
84+
85+
void CorsairCommanderCoreController::SendCommit()
86+
{
87+
if(!lastcolors.empty())
88+
{
89+
/*-----------------------------------------------------*\
90+
| If colors remain to be sent, send them |
91+
\*-----------------------------------------------------*/
92+
SetDirectColor(lastcolors, lastzones);
93+
}
94+
else
95+
{
96+
unsigned char usb_buf[1025];
97+
98+
/*-----------------------------------------------------*\
99+
| Zero out buffer |
100+
\*-----------------------------------------------------*/
101+
memset(usb_buf, 0x00, sizeof(usb_buf));
102+
103+
/*-----------------------------------------------------*\
104+
| Update last commit time |
105+
\*-----------------------------------------------------*/
106+
last_commit_time = std::chrono::steady_clock::now();
107+
108+
/*-----------------------------------------------------*\
109+
| Set up Commit packet |
110+
\*-----------------------------------------------------*/
111+
memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
112+
113+
usb_buf[0] = 0x00;
114+
usb_buf[1] = 0x08;
115+
usb_buf[2] = 0x06;
116+
usb_buf[4] = 0xBD;
117+
usb_buf[5] = 0x02;
118+
usb_buf[8] = 0x12;
119+
120+
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
121+
}
122+
}
123+
124+
125+
void CorsairCommanderCoreController::SendMultiPkt(unsigned char buffarray[][5], int r, int c)
126+
{
127+
/*---------------------------------------------------------*\
128+
| Private function to send multiple packets |
129+
\*---------------------------------------------------------*/
130+
unsigned char* hidtemp = new unsigned char[CORSAIR_COMMANDER_CORE_PACKET_SIZE];
131+
132+
for(unsigned int i = 0; i < r; i++)
133+
{
134+
memset(hidtemp, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
135+
136+
for(unsigned int j = 0; j < c; j++)
137+
{
138+
hidtemp[j+1] = buffarray[i][j];
139+
}
140+
141+
hid_write(dev, hidtemp, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
142+
hid_read(dev, hidtemp, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
143+
}
144+
}
145+
146+
void CorsairCommanderCoreController::SetDirectColor
147+
(
148+
std::vector<RGBColor> colors,
149+
std::vector<zone> zones
150+
)
151+
{
152+
if(controller_ready == 1 && ((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::milliseconds(33)))
153+
{
154+
lastcolors = colors;
155+
lastzones = zones;
156+
int packet_offset = CORSAIR_COMMANDER_CORE_PREAMBLE_OFFSET;
157+
int led_idx = 0;
158+
int channel_idx = 0;
159+
unsigned char* usb_buf = new unsigned char[CORSAIR_COMMANDER_CORE_PACKET_SIZE];
160+
161+
memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
162+
163+
/*-----------------------------------------------------*\
164+
| Prepare color information packet |
165+
\*-----------------------------------------------------*/
166+
usb_buf[0] = 0x00;
167+
usb_buf[1] = 0x08;
168+
usb_buf[2] = 0x06;
169+
usb_buf[4] = 0xBD;
170+
usb_buf[5] = 0x02;
171+
usb_buf[8] = 0x12;
172+
173+
for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++)
174+
{
175+
/*-------------------------------------------------*\
176+
| Add led colors |
177+
\*-------------------------------------------------*/
178+
for(unsigned int i = led_idx; i < led_idx + zones[zone_idx].leds_count; i++)
179+
{
180+
usb_buf[packet_offset] = RGBGetRValue(colors[i]);
181+
usb_buf[packet_offset+1] = RGBGetGValue(colors[i]);
182+
usb_buf[packet_offset+2] = RGBGetBValue(colors[i]);
183+
184+
packet_offset = packet_offset + 3;
185+
}
186+
187+
led_idx = led_idx + zones[zone_idx].leds_count;
188+
189+
/*-------------------------------------------------*\
190+
| Move offset for pump zone with less than 29 LEDs |
191+
\*-------------------------------------------------*/
192+
if(zone_idx == 0)
193+
{
194+
packet_offset = packet_offset + 3 * (29 - zones[zone_idx].leds_count);
195+
}
196+
197+
/*-------------------------------------------------*\
198+
| Move offset for fans with less than 34 LEDs |
199+
\*-------------------------------------------------*/
200+
if(zone_idx != 0)
201+
{
202+
packet_offset = packet_offset + 3 * (34 - zones[zone_idx].leds_count);
203+
}
204+
205+
channel_idx++;
206+
}
207+
208+
/*-----------------------------------------------------*\
209+
| Sending a direct mode color packet resets the timeout |
210+
\*-----------------------------------------------------*/
211+
last_commit_time = std::chrono::steady_clock::now();
212+
213+
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
214+
}
215+
}
216+
217+
void CorsairCommanderCoreController::SetFanMode()
218+
{
219+
/*--------------------------------------------------------------------------------------------------*\
220+
| Force controller to 6 QL fan mode to expose maximum number of LEDs per rgb port (34 LEDs per port) |
221+
\*--------------------------------------------------------------------------------------------------*/
222+
223+
unsigned char usb_buf[1025];
224+
225+
unsigned char buffarray4[][5] =
226+
{
227+
{0x08, 0x05, 0x01, 0x01, 0x00},
228+
{0x08, 0x0D, 0x01, 0x1E, 0x00},
229+
{0x08, 0x09, 0x01, 0x00, 0x00}
230+
};
231+
232+
SendMultiPkt(buffarray4, sizeof(buffarray4) / sizeof(buffarray4[0]), sizeof(buffarray4)[0] / sizeof(buffarray4[0][0]));
233+
234+
memset(usb_buf, 0, sizeof(usb_buf));
235+
236+
usb_buf[0] = 0x00;
237+
usb_buf[1] = 0x08;
238+
usb_buf[2] = 0x06;
239+
usb_buf[3] = 0x01;
240+
usb_buf[4] = 0x11;
241+
usb_buf[8] = 0x0D;
242+
usb_buf[10] = 0x07;
243+
usb_buf[11] = 0x01;
244+
usb_buf[12] = 0x08;
245+
246+
for(unsigned int i = 13; i < 25; i = i + 2)
247+
{
248+
usb_buf[i] = 0x01;
249+
usb_buf[i + 1] = 0x06;
250+
}
251+
252+
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
253+
hid_read(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
254+
255+
unsigned char buffarray2[][5] =
256+
{
257+
{0x08, 0x05, 0x01, 0x01, 0x00},
258+
{0x08, 0x15, 0x01, 0x00, 0x00}
259+
};
260+
261+
SendMultiPkt(buffarray2, sizeof(buffarray2) / sizeof(buffarray2[0]), sizeof(buffarray2)[0] / sizeof(buffarray2[0][0]));
262+
263+
memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
264+
265+
usb_buf[0] = 0x00;
266+
usb_buf[1] = 0x08;
267+
usb_buf[2] = 0x06;
268+
usb_buf[4] = 0xBD;
269+
usb_buf[5] = 0x02;
270+
usb_buf[8] = 0x12;
271+
272+
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
273+
hid_read(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
274+
275+
controller_ready = 1;
276+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*---------------------------------------------------------*\
2+
| CorsairCommanderCoreController.h |
3+
| |
4+
| Definitions for Corsair Commander Core |
5+
| Based on code by: |
6+
| Adam Honse ([email protected]), 8/17/2020 |
7+
| |
8+
| Jeff P. |
9+
\*---------------------------------------------------------*/
10+
11+
#include "RGBController.h"
12+
#include <vector>
13+
#include <chrono>
14+
#include <hidapi/hidapi.h>
15+
16+
#pragma once
17+
18+
#define CORSAIR_COMMANDER_CORE_PACKET_SIZE 1025
19+
#define CORSAIR_COMMANDER_CORE_PREAMBLE_OFFSET 10
20+
#define CORSAIR_ELITE_CAPELLIX_PUMP_LED_OFFSET 87
21+
#define CORSAIR_QL_FAN_ZONE_OFFSET 102
22+
#define CORSAIR_COMMANDER_CORE_NUM_CHANNELS 6
23+
24+
enum
25+
{
26+
CORSAIR_COMMANDER_CORE_MODE_DIRECT = 0x00,
27+
};
28+
29+
class CorsairCommanderCoreController
30+
{
31+
public:
32+
CorsairCommanderCoreController(hid_device* dev_handle, const char* path);
33+
~CorsairCommanderCoreController();
34+
35+
std::string GetLocationString();
36+
37+
void SetDirectColor
38+
(
39+
std::vector<RGBColor>,
40+
std::vector<zone>
41+
);
42+
43+
void KeepaliveThread();
44+
void SetFanMode();
45+
46+
private:
47+
hid_device* dev;
48+
std::thread* keepalive_thread;
49+
std::atomic<bool> keepalive_thread_run;
50+
std::atomic<bool> controller_ready;
51+
std::string location;
52+
std::vector<RGBColor> lastcolors;
53+
std::vector<zone> lastzones;
54+
std::chrono::time_point<std::chrono::steady_clock> last_commit_time;
55+
56+
void SendMultiPkt
57+
(
58+
unsigned char buffarray[][5],
59+
int r,
60+
int c
61+
);
62+
63+
void SendCommit();
64+
void InitController();
65+
};
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include "Detector.h"
2+
#include "CorsairCommanderCoreController.h"
3+
#include "RGBController.h"
4+
#include "RGBController_CorsairCommanderCore.h"
5+
#include <vector>
6+
#include <hidapi/hidapi.h>
7+
8+
/*-----------------------------------------------------*\
9+
| Corsair vendor ID |
10+
\*-----------------------------------------------------*/
11+
#define CORSAIR_VID 0x1B1C
12+
13+
/*-----------------------------------------------------*\
14+
| Commander Core product IDs |
15+
\*-----------------------------------------------------*/
16+
#define CORSAIR_H150I_COMMANDER_CORE_PID 0x0C1C
17+
18+
/******************************************************************************************\
19+
* *
20+
* DetectCorsairCapellixControllers *
21+
* *
22+
* Tests the USB address to see if a Corsair RGB Cooler controller exists there. *
23+
* *
24+
\******************************************************************************************/
25+
26+
void DetectCorsairCapellixHIDControllers(hid_device_info* info, const std::string& name)
27+
{
28+
hid_device* dev = hid_open_path(info->path);
29+
30+
if(dev)
31+
{
32+
CorsairCommanderCoreController* controller = new CorsairCommanderCoreController(dev, info->path);
33+
RGBController_CorsairCommanderCore* rgb_controller = new RGBController_CorsairCommanderCore(controller);
34+
35+
rgb_controller->name = name;
36+
37+
ResourceManager::get()->RegisterRGBController(rgb_controller);
38+
}
39+
}
40+
41+
REGISTER_HID_DETECTOR_PU("Corsair Commander Core", DetectCorsairCapellixHIDControllers, CORSAIR_VID, CORSAIR_H150I_COMMANDER_CORE_PID, 0xFF42, 0x01);

0 commit comments

Comments
 (0)