diff --git a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp index 9e239e3c..9461ea90 100644 --- a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp +++ b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp @@ -20,6 +20,8 @@ CorsairCommanderCoreController::CorsairCommanderCoreController(hid_device* dev_h location = path; keepalive_thread_run = 1; controller_ready = 0; + packet_size = CORSAIR_COMMANDER_CORE_PACKET_SIZE_V2; + command_res_size = packet_size - 4; /*-----------------------------------------------------*\ | Initialize controller | @@ -50,18 +52,38 @@ CorsairCommanderCoreController::~CorsairCommanderCoreController() void CorsairCommanderCoreController::InitController() { /*-----------------------------------------------------*\ - | Packet sequence to put controller into direct mode | + | Get version | \*-----------------------------------------------------*/ - unsigned char buffarray[][5] = - { - {0x08, 0x01, 0x03, 0x00, 0x02}, - {0x08, 0x0D, 0x00, 0x22, 0x00}, - }; + unsigned char command[2] = {0x02, 0x13}; + unsigned char* res = new unsigned char[command_res_size]; + SendCommand(command, NULL, 0, res); + version[0] = res[0]; + version[1] = res[1]; + version[2] = res[2]; + delete[] res; + + if(version[0] == 1) + { + packet_size = CORSAIR_COMMANDER_CORE_PACKET_SIZE_V1; + command_res_size = packet_size - 4; + } + + /*-----------------------------------------------------*\ + | Wake up device | + \*-----------------------------------------------------*/ + command[0] = 0x01; + command[1] = 0x03; + unsigned char cmd_data[2] = {0x00, 0x02}; + SendCommand(command, cmd_data, 2, NULL); - SendMultiPkt(buffarray, sizeof(buffarray) / sizeof(buffarray[0]), sizeof(buffarray)[0] / sizeof(buffarray[0][0])); SetFanMode(); } +std::string CorsairCommanderCoreController::GetFirmwareString() +{ + return "v"+std::to_string(version[0]) + "." + std::to_string(version[1]) + "." + std::to_string(version[2]); +} + std::string CorsairCommanderCoreController::GetLocationString() { return("HID: " + location); @@ -93,56 +115,126 @@ void CorsairCommanderCoreController::SendCommit() } else { - unsigned char usb_buf[1025]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - /*-----------------------------------------------------*\ | Update last commit time | \*-----------------------------------------------------*/ last_commit_time = std::chrono::steady_clock::now(); /*-----------------------------------------------------*\ - | Set up Commit packet | + | Send packet | \*-----------------------------------------------------*/ - memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - - usb_buf[0] = 0x00; - usb_buf[1] = 0x08; - usb_buf[2] = 0x06; - usb_buf[4] = 0xBD; - usb_buf[5] = 0x02; - usb_buf[8] = 0x12; - - hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE); + unsigned char command[2] = {0x01, 0x03}; + unsigned char cmd_data[2] = {0x00, 0x02}; + SendCommand(command, cmd_data, 2, NULL); } } -void CorsairCommanderCoreController::SendMultiPkt(unsigned char buffarray[][5], int r, int c) +void CorsairCommanderCoreController::SendCommand(unsigned char command[2], unsigned char data[], unsigned short int data_len, unsigned char res[]) { /*---------------------------------------------------------*\ - | Private function to send multiple packets | + | Private function to send a command | + | data_len must be <= 93 for V2 or <= 1021 for V1 | \*---------------------------------------------------------*/ - unsigned char* hidtemp = new unsigned char[CORSAIR_COMMANDER_CORE_PACKET_SIZE]; + unsigned char* buf = new unsigned char[packet_size]; - for(unsigned int i = 0; i < r; i++) + memset(buf, 0, packet_size); + buf[0] = 0x00; + buf[1] = 0x08; + + memcpy(&buf[2], command, 2); + if(data != NULL) { - memset(hidtemp, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - - for(unsigned int j = 0; j < c; j++) - { - hidtemp[j+1] = buffarray[i][j]; - } - - hid_write(dev, hidtemp, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - hid_read(dev, hidtemp, CORSAIR_COMMANDER_CORE_PACKET_SIZE); + memcpy(&buf[4], data, data_len); } - delete[] hidtemp; + hid_write(dev, buf, packet_size); + do + { + hid_read(dev, buf, packet_size); + } + while (buf[0] != 0x00); + + if(res != NULL) + { + memcpy(res, &buf[3], command_res_size); + } + + delete[] buf; +} + +void CorsairCommanderCoreController::WriteData(unsigned char endpoint[2], unsigned char data_type[2], unsigned char data[], unsigned short int data_len) +{ + /*---------------------------------------------------------*\ + | Private function to write data to an endpoint | + \*---------------------------------------------------------*/ + + /*---------------------------------------------------------*\ + | Open endpoint | + \*---------------------------------------------------------*/ + unsigned char command[2] = {0x0d, 0x00}; + SendCommand(command, endpoint, 2, NULL); + + + /*---------------------------------------------------------*\ + | Write data | + \*---------------------------------------------------------*/ + unsigned short int data_start_index = 0; + while(data_start_index < data_len) + { + if(data_start_index == 0) + { + /*---------------------------------------------------------*\ + | First packet | + \*---------------------------------------------------------*/ + int packet_data_len = packet_size - 10; + if(data_len < packet_data_len) + { + packet_data_len = data_len; + } + unsigned char* buf = new unsigned char[packet_data_len+6]; + unsigned short int real_len = data_len+2; + /*---------------------------------------------------------*\ + | Convert length to little endian | + \*---------------------------------------------------------*/ + buf[0] = (unsigned char) real_len & 0xFF; + buf[1] = (unsigned char) (real_len >> 8) & 0xFF; + buf[2] = 0x00; + buf[3] = 0x00; + memcpy(&buf[4], data_type, 2); + memcpy(&buf[6], data, packet_data_len); + + command[0] = 0x06; + command[1] = 0x00; + SendCommand(command, buf, packet_data_len+6, NULL); + delete[] buf; + data_start_index += packet_data_len; + } + else + { + /*-----------------------------------------------------------------------------------------------------*\ + | The rest of the packets | + | This command is not in v1 but it should never be reached as all data should fit in the first packet | + \*-----------------------------------------------------------------------------------------------------*/ + int packet_data_len = packet_size - 4; + if(data_len-data_start_index < packet_data_len) + { + packet_data_len = data_len-data_start_index; + } + + command[0] = 0x07; + command[1] = 0x00; + SendCommand(command, &data[data_start_index], packet_data_len, NULL); + data_start_index += packet_data_len; + } + } + + /*---------------------------------------------------------*\ + | Close endpoint | + \*---------------------------------------------------------*/ + command[0] = 0x05; + command[1] = 0x01; + SendCommand(command, NULL, 0, NULL); } void CorsairCommanderCoreController::SetDirectColor @@ -155,22 +247,12 @@ void CorsairCommanderCoreController::SetDirectColor { lastcolors = colors; lastzones = zones; - int packet_offset = CORSAIR_COMMANDER_CORE_PREAMBLE_OFFSET; + int packet_offset = 0; int led_idx = 0; int channel_idx = 0; - unsigned char* usb_buf = new unsigned char[CORSAIR_COMMANDER_CORE_PACKET_SIZE]; + unsigned char* usb_buf = new unsigned char[CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH]; - memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - - /*-----------------------------------------------------*\ - | Prepare color information packet | - \*-----------------------------------------------------*/ - usb_buf[0] = 0x00; - usb_buf[1] = 0x08; - usb_buf[2] = 0x06; - usb_buf[4] = 0xBD; - usb_buf[5] = 0x02; - usb_buf[8] = 0x12; + memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH); for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) { @@ -183,25 +265,24 @@ void CorsairCommanderCoreController::SetDirectColor usb_buf[packet_offset+1] = RGBGetGValue(colors[i]); usb_buf[packet_offset+2] = RGBGetBValue(colors[i]); - packet_offset = packet_offset + 3; + packet_offset += 3; } led_idx = led_idx + zones[zone_idx].leds_count; /*-------------------------------------------------*\ - | Move offset for pump zone with less than 33 LEDs | + | Move offset for pump zone with less than 29 LEDs | \*-------------------------------------------------*/ if(zone_idx == 0) { - packet_offset = packet_offset + 3 * (33 - zones[zone_idx].leds_count); + packet_offset += 3 * (29 - zones[zone_idx].leds_count); } - + else + { /*-------------------------------------------------*\ | Move offset for fans with less than 34 LEDs | \*-------------------------------------------------*/ - if(zone_idx != 0) - { - packet_offset = packet_offset + 3 * (34 - zones[zone_idx].leds_count); + packet_offset += 3 * (34 - zones[zone_idx].leds_count); } channel_idx++; @@ -212,7 +293,9 @@ void CorsairCommanderCoreController::SetDirectColor \*-----------------------------------------------------*/ last_commit_time = std::chrono::steady_clock::now(); - hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE); + unsigned char endpoint[2] = {0x22, 0x00}; + unsigned char data_type[2] = {0x12, 0x00}; + WriteData(endpoint, data_type, usb_buf, packet_offset); delete[] usb_buf; } @@ -224,57 +307,27 @@ void CorsairCommanderCoreController::SetFanMode() | Force controller to 6 QL fan mode to expose maximum number of LEDs per rgb port (34 LEDs per port) | \*--------------------------------------------------------------------------------------------------*/ - unsigned char usb_buf[1025]; + unsigned char endpoint[2] = {0x1E, 0x00}; + unsigned char data_type[2] = {0x0D, 0x00}; + unsigned char buf[15]; - unsigned char buffarray4[][5] = + /*-----------------------------------------------------*\ + | Set AIO mode | + \*-----------------------------------------------------*/ + buf[0] = 0x07; + buf[1] = 0x01; + buf[2] = 0x08; + + /*-----------------------------------------------------*\ + | SET fan modes | + \*-----------------------------------------------------*/ + for(unsigned int i = 3; i < 15; i = i + 2) { - {0x08, 0x05, 0x01, 0x01, 0x00}, - {0x08, 0x0D, 0x01, 0x1E, 0x00}, - {0x08, 0x09, 0x01, 0x00, 0x00} - }; - - SendMultiPkt(buffarray4, sizeof(buffarray4) / sizeof(buffarray4[0]), sizeof(buffarray4)[0] / sizeof(buffarray4[0][0])); - - memset(usb_buf, 0, sizeof(usb_buf)); - - usb_buf[0] = 0x00; - usb_buf[1] = 0x08; - usb_buf[2] = 0x06; - usb_buf[3] = 0x01; - usb_buf[4] = 0x11; - usb_buf[8] = 0x0D; - usb_buf[10] = 0x07; - usb_buf[11] = 0x01; - usb_buf[12] = 0x08; - - for(unsigned int i = 13; i < 25; i = i + 2) - { - usb_buf[i] = 0x01; - usb_buf[i + 1] = 0x06; + buf[i] = 0x01; + buf[i + 1] = 0x06; } - hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - hid_read(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - - unsigned char buffarray2[][5] = - { - {0x08, 0x05, 0x01, 0x01, 0x00}, - {0x08, 0x15, 0x01, 0x00, 0x00} - }; - - SendMultiPkt(buffarray2, sizeof(buffarray2) / sizeof(buffarray2[0]), sizeof(buffarray2)[0] / sizeof(buffarray2[0][0])); - - memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - - usb_buf[0] = 0x00; - usb_buf[1] = 0x08; - usb_buf[2] = 0x06; - usb_buf[4] = 0xBD; - usb_buf[5] = 0x02; - usb_buf[8] = 0x12; - - hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE); - hid_read(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE); + WriteData(endpoint, data_type, buf, 15); controller_ready = 1; } diff --git a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h index 25bb8ff4..17920c14 100644 --- a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h +++ b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h @@ -15,9 +15,9 @@ #pragma once -#define CORSAIR_COMMANDER_CORE_PACKET_SIZE 1025 -#define CORSAIR_COMMANDER_CORE_PREAMBLE_OFFSET 10 -#define CORSAIR_ELITE_CAPELLIX_PUMP_LED_OFFSET 87 +#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V1 1025 // First bit is the report bit +#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V2 97 // First bit is the report bit +#define CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH 699 #define CORSAIR_QL_FAN_ZONE_OFFSET 102 #define CORSAIR_COMMANDER_CORE_NUM_CHANNELS 6 @@ -32,6 +32,7 @@ public: CorsairCommanderCoreController(hid_device* dev_handle, const char* path); ~CorsairCommanderCoreController(); + std::string GetFirmwareString(); std::string GetLocationString(); void SetDirectColor @@ -51,14 +52,13 @@ private: std::string location; std::vector lastcolors; std::vector lastzones; + unsigned short int version[3] = {0, 0, 0}; + int packet_size; + int command_res_size; std::chrono::time_point last_commit_time; - void SendMultiPkt - ( - unsigned char buffarray[][5], - int r, - int c - ); + void SendCommand(unsigned char command[2], unsigned char data[], unsigned short int data_len, unsigned char res[]); + void WriteData(unsigned char endpoint[2], unsigned char data_type[2], unsigned char data[], unsigned short int data_len); void SendCommit(); void InitController(); diff --git a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp index 11807c9f..49be612d 100644 --- a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp +++ b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp @@ -13,7 +13,7 @@ /*-----------------------------------------------------*\ | Commander Core product IDs | \*-----------------------------------------------------*/ -#define CORSAIR_H150I_COMMANDER_CORE_PID 0x0C1C +#define CORSAIR_COMMANDER_CORE_PID 0x0C1C /******************************************************************************************\ * * @@ -38,4 +38,4 @@ void DetectCorsairCapellixHIDControllers(hid_device_info* info, const std::strin } } -REGISTER_HID_DETECTOR_PU("Corsair Commander Core", DetectCorsairCapellixHIDControllers, CORSAIR_VID, CORSAIR_H150I_COMMANDER_CORE_PID, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCapellixHIDControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE_PID, 0x00, 0xFF42, 0x01); diff --git a/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp b/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp index 595a4c97..28b2acbf 100644 --- a/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp +++ b/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp @@ -19,12 +19,25 @@ @comment \*-------------------------------------------------------------------*/ +#define NA 0xFFFFFFFF +static unsigned int matrix_map[7][7] = +{ + { 28, NA, 27, NA, 26, NA, 25 }, + { NA, 16, NA, 15, NA, 14, NA }, + { 17, NA, 0, 5, 3, NA, 24 }, + { NA, 9, 4, 8, 6, 13, NA }, + { 18, NA, 1, 7, 2, NA, 23 }, + { NA, 10, NA, 11, NA, 12, NA }, + { 19, NA, 20, NA, 21, NA, 22 }, +}; + RGBController_CorsairCommanderCore::RGBController_CorsairCommanderCore(CorsairCommanderCoreController* controller_ptr) { controller = controller_ptr; vendor = "Corsair"; description = "Corsair Commander Core"; + version = controller->GetFirmwareString(); type = DEVICE_TYPE_COOLER; location = controller->GetLocationString(); @@ -55,9 +68,14 @@ void RGBController_CorsairCommanderCore::SetupZones() zones.resize(7); zones[0].name = "Pump"; - zones[0].type = ZONE_TYPE_LINEAR; - zones[0].leds_min = 0; - zones[0].leds_max = 33; + zones[0].type = ZONE_TYPE_MATRIX; + zones[0].leds_min = 29; + zones[0].leds_max = 29; + zones[0].leds_count = 29; + zones[0].matrix_map = new matrix_map_type; + zones[0].matrix_map->height = 7; + zones[0].matrix_map->width = 7; + zones[0].matrix_map->map = (unsigned int *)&matrix_map; for(unsigned int i = 1; i < (CORSAIR_COMMANDER_CORE_NUM_CHANNELS + 1); i++) {