Files
OpenRGB/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp
Chris de3d2c7e22 Initial commit for the Corsair K60 RGB PRO to resolve #1240
+ Adding K60 and K60 Low Profile PID to CorsairPeripheralV2Devices.h
+ Adding device layout
+ Registering detector
+ Adding pointer layout map and changing calls to accomodate.
2022-11-18 17:26:25 +00:00

291 lines
9.3 KiB
C++

/*---------------------------------------------------------------------*\
| CorsairPeripheralV2Controller.cpp |
| |
| Base class for the 08 based Corsair protocol |
| |
| Chris M (Dr_No) 07 Aug 2022 |
| |
\*---------------------------------------------------------------------*/
#include "CorsairPeripheralV2Controller.h"
CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_handle, const char* path, std::string /*name*/, uint16_t pid)
{
const uint8_t sz = HID_MAX_STR;
wchar_t tmp[sz];
dev = dev_handle;
location = path;
hid_get_manufacturer_string(dev, tmp, sz);
std::wstring wName = std::wstring(tmp);
device_name = std::string(wName.begin(), wName.end());
hid_get_product_string(dev, tmp, sz);
wName = std::wstring(tmp);
device_name.append(" ").append(std::string(wName.begin(), wName.end()));
for(size_t i = 0; i < CORSAIR_V2_DEVICE_COUNT; i++)
{
if(corsair_v2_device_list[i]->pid == pid)
{
/*---------------------------------------------------------*\
| Set device ID |
\*---------------------------------------------------------*/
device_index = i;
write_cmd = CORSAIR_V2_WRITE_ID + corsair_v2_device_list[device_index]->wireless;
}
}
/*---------------------------------------------------------*\
| Possibly is Wireless connected? |
\*---------------------------------------------------------*/
GetAddress(0x11);
}
CorsairPeripheralV2Controller::~CorsairPeripheralV2Controller()
{
hid_close(dev);
}
const corsair_v2_device* CorsairPeripheralV2Controller::GetDeviceData()
{
return corsair_v2_device_list[device_index];
}
std::string CorsairPeripheralV2Controller::GetDeviceLocation()
{
return("HID: " + location);
}
std::string CorsairPeripheralV2Controller::GetFirmwareString()
{
return "";
}
std::string CorsairPeripheralV2Controller::GetName()
{
return device_name;
}
std::string CorsairPeripheralV2Controller::GetSerialString()
{
const uint8_t sz = HID_MAX_STR;
wchar_t tmp[sz];
int ret = hid_get_serial_number_string(dev, tmp, sz);
if(ret != 0)
{
LOG_DEBUG("[%s] Get HID Serial string failed", device_name.c_str());
return("");
}
std::wstring w_tmp = std::wstring(tmp);
std::string serial = std::string(w_tmp.begin(), w_tmp.end());
return serial;
}
void CorsairPeripheralV2Controller::SetRenderMode(corsair_v2_device_mode mode)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
/*---------------------------------------------------------*\
| Set Mode |
\*---------------------------------------------------------*/
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_SET;
buffer[3] = CORSAIR_V2_VALUE_MODE;
buffer[5] = mode;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
}
void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1, uint8_t opt2)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
/*---------------------------------------------------------*\
| The Corsair command is the same for each initialisation |
| packet and the registers and options differ for |
| each peripheral supported by the protocol |
\*---------------------------------------------------------*/
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_GET;
buffer[3] = opt1;
buffer[5] = 0x00;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
/*---------------------------------------------------------*\
| Open a RGB lighting handle |
\*---------------------------------------------------------*/
buffer[2] = 0x0D;
buffer[3] = 0x00;
buffer[4] = 0x01;
buffer[5] = opt2;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
}
void CorsairPeripheralV2Controller::GetAddress(uint8_t address)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
uint8_t read[CORSAIR_V2_WRITE_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
memset(read, 0, CORSAIR_V2_WRITE_SIZE);
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_GET;
buffer[3] = address;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
hid_read(dev, read, CORSAIR_V2_WRITE_SIZE);
LOG_DEBUG("[%s] GetAddress %02X - %02X %02X - %02X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(),
address, read[0], read[1], read[2], read[3], read[4], read[5], read[6], read[7], read[8], read[9]);
}
void CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_START_TX;
buffer[3] = opt1;
buffer[4] = 0x01;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
}
void CorsairPeripheralV2Controller::StopTransaction(uint8_t opt1)
{
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_STOP_TX;
buffer[3] = 0x01;
buffer[4] = opt1;
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
}
void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size)
{
const uint8_t offset1 = 8;
const uint8_t offset2 = 4;
uint16_t remaining = data_size;
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
StartTransaction(0);
/*---------------------------------------------------------*\
| Set the data header in packet 1 with the data length |
| signaling how many packets to expect to the device |
\*---------------------------------------------------------*/
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_BLK_W1;
buffer[4] = data_size & 0xFF;
buffer[5] = data_size >> 8;
/*---------------------------------------------------------*\
| Check if the data needs more than 1 packet |
\*---------------------------------------------------------*/
uint16_t copy_bytes = CORSAIR_V2_WRITE_SIZE - offset1;
if(remaining < copy_bytes)
{
copy_bytes = remaining;
}
memcpy(&buffer[offset1], &data[0], copy_bytes);
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
remaining -= copy_bytes;
buffer[2] = CORSAIR_V2_CMD_BLK_WN;
copy_bytes = CORSAIR_V2_WRITE_SIZE - offset2;
/*---------------------------------------------------------*\
| Send the remaining packets |
\*---------------------------------------------------------*/
while(remaining)
{
uint16_t index = data_size - remaining;
if(remaining < copy_bytes)
{
memset(&buffer[offset2], 0, copy_bytes);
copy_bytes = remaining;
}
memcpy(&buffer[offset2], &data[index], copy_bytes);
hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE);
remaining -= copy_bytes;
}
StopTransaction(0);
}
void CorsairPeripheralV2Controller::UpdateHWMode(uint16_t mode, corsair_v2_color /*color_mode*/, uint8_t /*speed*/,
uint8_t /*direction*/, uint8_t /*brightness*/, std::vector<RGBColor> /*colors*/)
{
/*---------------------------------------------------------*\
| If we are switching to `Direct` mode |
| set device in software mode |
\*---------------------------------------------------------*/
if(mode == CORSAIR_V2_MODE_DIRECT)
{
SetRenderMode(CORSAIR_V2_MODE_SW);
return;
}
/*
SetRenderMode(CORSAIR_V2_MODE_HW);
uint8_t buffer[CORSAIR_V2_WRITE_SIZE];
memset(buffer, 0, CORSAIR_V2_WRITE_SIZE);
*/
/*---------------------------------------------------------*\
| Set the data header in packet 1 with the data length |
| signaling how many packets to expect to the device |
\*---------------------------------------------------------*/
/*
buffer[1] = write_cmd;
buffer[2] = CORSAIR_V2_CMD_BLK_W1;
buffer[3] = CORSAIR_V2_MODE_HW;
buffer[4] = 0x30;
buffer[8] = mode & 0xFF;
buffer[9] = mode >> 8;
buffer[10] = CORSAIR_V2_COLOR_SPECIFIC;
buffer[11] = speed;
buffer[14] = colors.size();
for(size_t i = 0; i < colors.size(); ++i)
{
uint8_t offset = 15 + (i * 4);
buffer[offset] = brightness;
buffer[offset + 1] = RGBGetBValue(colors[i]);
buffer[offset + 2] = RGBGetGValue(colors[i]);
buffer[offset + 3] = RGBGetRValue(colors[i]);
}
*/
}