Initial Corsair Commander Pro support, it's the same protocol as the Lighting Node Pro but on a different endpoint

This commit is contained in:
Adam Honse
2020-01-16 21:25:39 -06:00
parent cf2c2d6b93
commit 48ba8435b1
7 changed files with 613 additions and 0 deletions

View File

@@ -0,0 +1,345 @@
/*---------------------------------------------------------*\
| Processing Code for Corsair Commander Pro |
| |
| Adam Honse (calcprogrammer1@gmail.com), 1/16/2020 |
\*---------------------------------------------------------*/
#include "CorsairCmdrProController.h"
#include <fstream>
#include <iostream>
#include <string>
//Include thread libraries for Windows or Linux
#ifdef WIN32
#include <process.h>
#else
#include "pthread.h"
#include "unistd.h"
#endif
//Thread functions have different types in Windows and Linux
#ifdef WIN32
#define THREAD static void
#define THREADRETURN
#else
#define THREAD static void*
#define THREADRETURN return(NULL);
#endif
#ifdef WIN32
#include <Windows.h>
#else
#include <unistd.h>
static void Sleep(unsigned int milliseconds)
{
usleep(1000 * milliseconds);
}
#endif
THREAD keepalive_thread(void *param)
{
CorsairCmdrProController* corsair = static_cast<CorsairCmdrProController*>(param);
corsair->KeepaliveThread();
THREADRETURN
}
CorsairCmdrProController::CorsairCmdrProController(libusb_device_handle* dev_handle)
{
dev = dev_handle;
channel_leds[0] = 60;
channel_leds[1] = 60;
/*-----------------------------------------------------*\
| The Corsair Lighting Node Pro requires a packet within|
| 20 seconds of sending the lighting change in order |
| to not revert back into rainbow mode. Start a thread |
| to continuously send a keepalive packet every 5s |
\*-----------------------------------------------------*/
#ifdef WIN32
_beginthread(keepalive_thread, 0, this);
#else
pthread_t thread;
pthread_create(&thread, NULL, &keepalive_thread, this);
#endif
}
CorsairCmdrProController::~CorsairCmdrProController()
{
}
void CorsairCmdrProController::SendKeepalive()
{
unsigned char usb_apply[] =
{
0x33, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
int actual;
/*-----------------------------------------------------*\
| Send apply packet |
\*-----------------------------------------------------*/
libusb_interrupt_transfer(dev, 0x01, usb_apply, 64, &actual, 0);
}
void CorsairCmdrProController::KeepaliveThread()
{
while(1)
{
SendKeepalive();
Sleep(5000);
}
}
void CorsairCmdrProController::SetChannelLEDs(unsigned int channel, std::vector<RGBColor> colors)
{
unsigned char usb_start[] =
{
0x38, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char usb_data[] =
{
0x32, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char usb_apply[] =
{
0x33, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
int actual;
/*-----------------------------------------------------*\
| Set channel in USB packets |
\*-----------------------------------------------------*/
usb_data[0x01] = channel;
usb_start[0x01] = channel;
/*-----------------------------------------------------*\
| Send start packet |
\*-----------------------------------------------------*/
libusb_interrupt_transfer(dev, 0x02, usb_start, 64, &actual, 0);
/*-----------------------------------------------------*\
| Send red channel packet 1 |
\*-----------------------------------------------------*/
std::size_t pkt_max = 50;
if(pkt_max > colors.size())
{
pkt_max = colors.size();
}
usb_data[0x02] = 0;
usb_data[0x03] = pkt_max;
usb_data[0x04] = 0x00; //red
for (std::size_t idx = 0; idx < pkt_max; idx++)
{
RGBColor color = colors[idx];
usb_data[idx + 5] = RGBGetRValue(color);
}
libusb_interrupt_transfer(dev, 0x02, usb_data, 64, &actual, 0);
/*-----------------------------------------------------*\
| Send red channel packet 2 if necessary |
\*-----------------------------------------------------*/
for(int idx = 4; idx < 64; idx++)
{
usb_data[idx] = 0;
}
pkt_max = 0;
if (colors.size() > 50)
{
pkt_max = colors.size() - 50;
}
if(pkt_max > 0)
{
usb_data[0x02] = 50;
usb_data[0x03] = pkt_max;
usb_data[0x04] = 0x00; //red
for (std::size_t idx = 0; idx < pkt_max; idx++)
{
RGBColor color = colors[idx + 50];
usb_data[idx + 5] = RGBGetRValue(color);
}
libusb_interrupt_transfer(dev, 0x02, usb_data, 64, &actual, 0);
}
/*-----------------------------------------------------*\
| Send green channel packet 1 |
\*-----------------------------------------------------*/
pkt_max = 50;
if(pkt_max > colors.size())
{
pkt_max = colors.size();
}
usb_data[0x02] = 0;
usb_data[0x03] = pkt_max;
usb_data[0x04] = 0x01; //green
for (std::size_t idx = 0; idx < pkt_max; idx++)
{
RGBColor color = colors[idx];
usb_data[idx + 5] = RGBGetGValue(color);
}
libusb_interrupt_transfer(dev, 0x02, usb_data, 64, &actual, 0);
/*-----------------------------------------------------*\
| Send green channel packet 2 if necessary |
\*-----------------------------------------------------*/
for(int idx = 4; idx < 64; idx++)
{
usb_data[idx] = 0;
}
pkt_max = 0;
if (colors.size() > 50)
{
pkt_max = colors.size() - 50;
}
if(pkt_max > 0)
{
usb_data[0x02] = 50;
usb_data[0x03] = pkt_max;
usb_data[0x04] = 0x01; //green
for (std::size_t idx = 0; idx < pkt_max; idx++)
{
RGBColor color = colors[idx + 50];
usb_data[idx + 5] = RGBGetGValue(color);
}
libusb_interrupt_transfer(dev, 0x02, usb_data, 64, &actual, 0);
}
/*-----------------------------------------------------*\
| Send blue channel packet 1 |
\*-----------------------------------------------------*/
pkt_max = 50;
if(pkt_max > colors.size())
{
pkt_max = colors.size();
}
usb_data[0x02] = 0;
usb_data[0x03] = pkt_max;
usb_data[0x04] = 0x02; //blue
for (std::size_t idx = 0; idx < pkt_max; idx++)
{
RGBColor color = colors[idx];
usb_data[idx + 5] = RGBGetBValue(color);
}
libusb_interrupt_transfer(dev, 0x02, usb_data, 64, &actual, 0);
/*-----------------------------------------------------*\
| Send blue channel packet 2 if necessary |
\*-----------------------------------------------------*/
for(int idx = 4; idx < 64; idx++)
{
usb_data[idx] = 0;
}
pkt_max = 0;
if (colors.size() > 50)
{
pkt_max = colors.size() - 50;
}
if(pkt_max > 0)
{
usb_data[0x02] = 50;
usb_data[0x03] = pkt_max;
usb_data[0x04] = 0x02; //blue
for (std::size_t idx = 0; idx < pkt_max; idx++)
{
RGBColor color = colors[idx + 50];
usb_data[idx + 5] = RGBGetBValue(color);
}
libusb_interrupt_transfer(dev, 0x02, usb_data, 64, &actual, 0);
}
/*-----------------------------------------------------*\
| Send apply packet |
\*-----------------------------------------------------*/
libusb_interrupt_transfer(dev, 0x02, usb_apply, 64, &actual, 0);
}

View File

@@ -0,0 +1,37 @@
/*---------------------------------------------------------*\
| Definitions for Corsair Commander Pro |
| |
| Adam Honse (calcprogrammer1@gmail.com), 1/16/2020 |
\*---------------------------------------------------------*/
#include "RGBController.h"
#include <vector>
#include <libusb-1.0/libusb.h>
#pragma once
enum
{
CORSAIR_CMDR_PRO_CHANNEL_1 = 0x00, /* Channel 1 */
CORSAIR_CMDR_PRO_CHANNEL_2 = 0x01, /* Channel 2 */
CORSAIR_CMDR_PRO_NUM_CHANNELS = 0x02 /* Number of channels */
};
class CorsairCmdrProController
{
public:
CorsairCmdrProController(libusb_device_handle* dev_handle);
~CorsairCmdrProController();
char* GetLEDString();
unsigned int GetStripsOnChannel(unsigned int channel);
void SetChannelEffect(unsigned int channel, unsigned int mode, std::vector<RGBColor> colors);
void SetChannelLEDs(unsigned int channel, std::vector<RGBColor> colors);
void SendKeepalive();
unsigned int channel_leds[CORSAIR_CMDR_PRO_NUM_CHANNELS];
void KeepaliveThread();
private:
libusb_device_handle* dev;
};

View File

@@ -0,0 +1,37 @@
#include "CorsairCmdrProController.h"
#include "RGBController.h"
#include "RGBController_CorsairCmdrPro.h"
#include <vector>
#include <libusb-1.0/libusb.h>
#define CORSAIR_COMMANDER_PRO_VID 0x1B1C
#define CORSAIR_COMMANDER_PRO_PID 0x0C10
/******************************************************************************************\
* *
* DetectCorsairCmdrProControllers *
* *
* Detect devices supported by the Corsair Commander Pro driver *
* * *
\******************************************************************************************/
void DetectCorsairCmdrProControllers(std::vector<RGBController*> &rgb_controllers)
{
libusb_context * ctx;
libusb_init(&ctx);
//Look for Corsair Commander Pro
libusb_device_handle * dev = libusb_open_device_with_vid_pid(ctx, CORSAIR_COMMANDER_PRO_VID, CORSAIR_COMMANDER_PRO_PID);
if( dev )
{
libusb_detach_kernel_driver(dev, 0);
libusb_claim_interface(dev, 0);
CorsairCmdrProController* controller = new CorsairCmdrProController(dev);
RGBController_CorsairCmdrPro* rgb_controller = new RGBController_CorsairCmdrPro(controller);
rgb_controllers.push_back(rgb_controller);
}
} /* DetectCorsairCmdrProControllers() */

View File

@@ -334,6 +334,7 @@ void DetectAMDWraithPrismControllers(std::vector<RGBController*>& rgb_controller
void DetectAorusGPUControllers(std::vector<RGBController*> &rgb_controllers);
void DetectMSI3ZoneControllers(std::vector<RGBController*>& rgb_controllers);
void DetectPoseidonZRGBControllers(std::vector<RGBController*>& rgb_controllers);
void DetectCorsairCmdrProControllers(std::vector<RGBController*> &rgb_controllers);
void DetectCorsairNodeProControllers(std::vector<RGBController*> &rgb_controllers);
/******************************************************************************************\
@@ -363,6 +364,7 @@ void DetectRGBControllers(void)
DetectAMDWraithPrismControllers(rgb_controllers);
DetectMSI3ZoneControllers(rgb_controllers);
DetectPoseidonZRGBControllers(rgb_controllers);
DetectCorsairCmdrProControllers(rgb_controllers);
DetectCorsairNodeProControllers(rgb_controllers);
DetectE131Controllers(rgb_controllers);

View File

@@ -14,6 +14,7 @@ INCLUDEPATH += \
Controllers/AMDWraithPrismController/ \
Controllers/AuraController/ \
Controllers/CorsairController/ \
Controllers/CorsairCmdrProController/ \
Controllers/CorsairNodeProController/ \
Controllers/CorsairProController/ \
Controllers/Hue2Controller/ \
@@ -48,6 +49,8 @@ SOURCES += \
Controllers/AuraController/AuraControllerDetect.cpp \
Controllers/CorsairController/CorsairController.cpp \
Controllers/CorsairController/CorsairControllerDetect.cpp \
Controllers/CorsairCmdrProController/CorsairCmdrProController.cpp \
Controllers/CorsairCmdrProController/CorsairCmdrProControllerDetect.cpp \
Controllers/CorsairNodeProController/CorsairNodeProController.cpp \
Controllers/CorsairNodeProController/CorsairNodeProControllerDetect.cpp \
Controllers/CorsairProController/CorsairProController.cpp \
@@ -75,6 +78,7 @@ SOURCES += \
RGBController/RGBController_AMDWraithPrism.cpp \
RGBController/RGBController_Aura.cpp \
RGBController/RGBController_Corsair.cpp \
RGBController/RGBController_CorsairCmdrPro.cpp \
RGBController/RGBController_CorsairNodePro.cpp \
RGBController/RGBController_CorsairPro.cpp \
RGBController/RGBController_Hue2.cpp \
@@ -102,6 +106,7 @@ HEADERS += \
Controllers/AMDWraithPrismController/AMDWraithPrismController.h \
Controllers/AuraController/AuraController.h \
Controllers/CorsairController/CorsairController.h \
Controllers/CorsairCmdrProController/CorsairCmdrProController.h \
Controllers/CorsairNodeProController/CorsairNodeProController.h \
Controllers/CorsairProController/CorsairProController.h \
Controllers/Hue2Controller/Hue2Controller.h \
@@ -117,6 +122,7 @@ HEADERS += \
RGBController/RGBController_AMDWraithPrism.h \
RGBController/RGBController_Aura.h \
RGBController/RGBController_Corsair.h \
RGBController/RGBController_CorsairCmdrPro.h \
RGBController/RGBController_CorsairNodePro.h \
RGBController/RGBController_CorsairPro.h \
RGBController/RGBController_E131.h \

View File

@@ -0,0 +1,156 @@
/*-----------------------------------------*\
| RGBController_CorsairCmdrPro.cpp |
| |
| Generic RGB Interface for Corsair |
| Commander Pro |
| |
| Adam Honse (CalcProgrammer1) 1/16/2020 |
\*-----------------------------------------*/
#include "RGBController_CorsairCmdrPro.h"
RGBController_CorsairCmdrPro::RGBController_CorsairCmdrPro(CorsairCmdrProController* corsair_ptr)
{
corsair = corsair_ptr;
name = "Corsair Commander Pro";
type = DEVICE_TYPE_LEDSTRIP;
mode led_mode;
led_mode.name = "Custom";
modes.push_back(led_mode);
/*-------------------------------------------------*\
| Set size of colors array |
\*-------------------------------------------------*/
unsigned int led_count = 0;
for (unsigned int channel_idx = 0; channel_idx < CORSAIR_CMDR_PRO_NUM_CHANNELS; channel_idx++)
{
led_count += corsair->channel_leds[channel_idx];
}
colors.resize(led_count);
/*-------------------------------------------------*\
| Set zones and leds |
\*-------------------------------------------------*/
unsigned int led_idx = 0;
for (unsigned int channel_idx = 0; channel_idx < CORSAIR_CMDR_PRO_NUM_CHANNELS; channel_idx++)
{
if(corsair->channel_leds[channel_idx] > 0)
{
zone* new_zone = new zone;
char ch_idx_string[2];
sprintf(ch_idx_string, "%d", channel_idx + 1);
new_zone->name = "Corsair Channel ";
new_zone->name.append(ch_idx_string);
new_zone->type = ZONE_TYPE_LINEAR;
std::vector<int> *new_zone_map = new std::vector<int>();
for (unsigned int led_ch_idx = 0; led_ch_idx < corsair->channel_leds[channel_idx]; led_ch_idx++)
{
char led_idx_string[3];
sprintf(led_idx_string, "%d", led_ch_idx + 1);
led new_led;
new_led.name = "Corsair Channel ";
new_led.name.append(ch_idx_string);
new_led.name.append(", LED ");
new_led.name.append(led_idx_string);
leds.push_back(new_led);
leds_channel.push_back(channel_idx);
new_zone_map->push_back(led_idx);
led_idx++;
}
new_zone->map.push_back(*new_zone_map);
zones.push_back(*new_zone);
zones_channel.push_back(channel_idx);
}
}
}
int RGBController_CorsairCmdrPro::GetMode()
{
return 0;
}
void RGBController_CorsairCmdrPro::SetMode(int /*mode*/)
{
}
void RGBController_CorsairCmdrPro::SetCustomMode()
{
}
void RGBController_CorsairCmdrPro::UpdateLEDs()
{
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
{
unsigned int channel = zones_channel[zone_idx];
std::vector<RGBColor> channel_colors;
for(std::size_t color = 0; color < colors.size(); color++)
{
if(leds_channel[color] == channel)
{
channel_colors.push_back(colors[color]);
}
}
if(channel_colors.size() > 0)
{
corsair->SetChannelLEDs(channel, channel_colors);
}
}
}
void RGBController_CorsairCmdrPro::UpdateZoneLEDs(int zone)
{
unsigned int channel = zones_channel[zone];
std::vector<RGBColor> channel_colors;
for(std::size_t color = 0; color < colors.size(); color++)
{
if(leds_channel[color] == channel)
{
channel_colors.push_back(colors[color]);
}
}
if(channel_colors.size() > 0)
{
//corsair->SetChannelLEDs(channel, channel_colors);
}
corsair->SendKeepalive();
}
void RGBController_CorsairCmdrPro::UpdateSingleLED(int led)
{
unsigned int channel = leds_channel[led];
std::vector<RGBColor> channel_colors;
for(std::size_t color = 0; color < colors.size(); color++)
{
if(leds_channel[color] == channel)
{
channel_colors.push_back(colors[color]);
}
}
if(channel_colors.size() > 0)
{
corsair->SetChannelLEDs(channel, channel_colors);
}
}

View File

@@ -0,0 +1,30 @@
/*-----------------------------------------*\
| RGBController_CorsairCmdrPro.h |
| |
| Generic RGB Interface for Corsair |
| Commander Pro |
| |
| Adam Honse (CalcProgrammer1) 1/16/2020 |
\*-----------------------------------------*/
#pragma once
#include "RGBController.h"
#include "serial_port.h"
#include "CorsairCmdrProController.h"
class RGBController_CorsairCmdrPro : public RGBController
{
public:
RGBController_CorsairCmdrPro(CorsairCmdrProController* corsair_ptr);
int GetMode();
void SetMode(int mode);
void SetCustomMode();
void UpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
private:
CorsairCmdrProController* corsair;
std::vector<unsigned int> leds_channel;
std::vector<unsigned int> zones_channel;
};