From baf5d30b27fe5125d17a0df57838eac4234ff01b Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 12 Mar 2023 17:40:09 +1100 Subject: [PATCH] Initial commit for the Corsair M55 mouse * Added config to CorsairPeripheralV2Devices * Adding device config to CorsairPeripheralV2Devices.cpp * Extending the base CorsairPeripheralV2Controller to CorsairPeripheralV2HWController to account for HW modes * Minor adjustments to the CorsairPeripheralV2SWController to accommodate * Resolves #1951 --- .../CorsairPeripheralV2Controller.cpp | 38 ++- .../CorsairPeripheralV2Controller.h | 69 ++--- .../CorsairPeripheralV2ControllerDetect.cpp | 17 +- .../CorsairPeripheralV2Devices.cpp | 59 ++++- .../CorsairPeripheralV2Devices.h | 11 +- .../CorsairPeripheralV2HardwareController.cpp | 89 +++++++ .../CorsairPeripheralV2HardwareController.h | 32 +++ .../RGBController_CorsairV2Hardware.cpp | 247 ++++++++++++++++++ .../RGBController_CorsairV2Hardware.h | 42 +++ .../RGBController_CorsairV2Software.cpp | 9 +- .../RGBController_CorsairV2Software.h | 1 + OpenRGB.pro | 4 + 12 files changed, 569 insertions(+), 49 deletions(-) create mode 100644 Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp create mode 100644 Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h create mode 100644 Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp create mode 100644 Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp index 391ca4d54..c82446f5d 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp @@ -9,6 +9,8 @@ #include "CorsairPeripheralV2Controller.h" +using namespace std::chrono_literals; + CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_handle, const char* path, std::string /*name*/, uint16_t pid) { const uint8_t sz = HID_MAX_STR; @@ -33,14 +35,29 @@ CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_han | Set device ID | \*---------------------------------------------------------*/ device_index = i; - write_cmd = CORSAIR_V2_WRITE_ID + corsair_v2_device_list[device_index]->wireless; } } /*---------------------------------------------------------*\ - | Possibly is Wireless connected? | + | NB: If the device is not found in the device list | + | then wireless mode may not work reliably | + \*---------------------------------------------------------*/ + bool wireless = corsair_v2_device_list[device_index]->wireless; + if(wireless) + { + write_cmd = CORSAIR_V2_WRITE_WIRELESS_ID; + } + LOG_DEBUG("[%s] Setting write CMD to %02X for %s mode", device_name.c_str(), + write_cmd, (wireless) ? "wireless" : "wired" ); + + /*---------------------------------------------------------*\ + | Get VID | \*---------------------------------------------------------*/ GetAddress(0x11); + /*---------------------------------------------------------*\ + | Get PID | + \*---------------------------------------------------------*/ + GetAddress(0x12); } CorsairPeripheralV2Controller::~CorsairPeripheralV2Controller() @@ -102,6 +119,8 @@ void CorsairPeripheralV2Controller::SetRenderMode(corsair_v2_device_mode mode) buffer[5] = mode; hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); } void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1, uint8_t opt2) @@ -121,6 +140,8 @@ void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1, uint8_t opt2) buffer[5] = 0x00; hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); /*---------------------------------------------------------*\ | Open a RGB lighting handle | @@ -131,6 +152,8 @@ void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1, uint8_t opt2) buffer[5] = opt2; hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); } void CorsairPeripheralV2Controller::GetAddress(uint8_t address) @@ -146,7 +169,8 @@ void CorsairPeripheralV2Controller::GetAddress(uint8_t address) buffer[3] = address; hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); - hid_read(dev, read, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, read, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); 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]); @@ -164,6 +188,8 @@ void CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1) buffer[4] = 0x01; hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); } void CorsairPeripheralV2Controller::StopTransaction(uint8_t opt1) @@ -178,6 +204,8 @@ void CorsairPeripheralV2Controller::StopTransaction(uint8_t opt1) buffer[4] = opt1; hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); } void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size) @@ -211,6 +239,8 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size) memcpy(&buffer[offset1], &data[0], copy_bytes); hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); remaining -= copy_bytes; buffer[2] = CORSAIR_V2_CMD_BLK_WN; @@ -231,6 +261,8 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size) memcpy(&buffer[offset2], &data[index], copy_bytes); hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + std::this_thread::sleep_for(2ms); + hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); remaining -= copy_bytes; } diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h index 626d47abf..81d423b4a 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h @@ -16,48 +16,50 @@ #include "RGBController.h" #include "CorsairPeripheralV2Devices.h" -#define NA 0xFFFFFFFF -#define HID_MAX_STR 255 +#define NA 0xFFFFFFFF +#define HID_MAX_STR 255 -#define CORSAIR_V2_WRITE_ID 8 -#define CORSAIR_V2_VALUE_MODE 3 -#define CORSAIR_V2_WRITE_SIZE 65 +#define CORSAIR_V2_TIMEOUT 100 +#define CORSAIR_V2_VALUE_MODE 3 +#define CORSAIR_V2_WRITE_WIRED_ID 8 +#define CORSAIR_V2_WRITE_WIRELESS_ID 9 +#define CORSAIR_V2_WRITE_SIZE 65 -#define CORSAIR_V2_BRIGHTNESS_MIN 0 -#define CORSAIR_V2_BRIGHTNESS_MAX 0xFF +#define CORSAIR_V2_BRIGHTNESS_MIN 0 +#define CORSAIR_V2_BRIGHTNESS_MAX 0xFF enum corsair_v2_cmd { - CORSAIR_V2_CMD_SET = 0x01, /* Command for setting values */ - CORSAIR_V2_CMD_GET = 0x02, /* Command for getting values */ - CORSAIR_V2_CMD_STOP_TX = 0x05, /* Finish Transaction */ - CORSAIR_V2_CMD_BLK_W1 = 0x06, /* Block write packet 1 */ - CORSAIR_V2_CMD_BLK_WN = 0x07, /* Block write remaining packets */ - CORSAIR_V2_CMD_START_TX = 0x0D, /* Start Transaction */ + CORSAIR_V2_CMD_SET = 0x01, /* Command for setting values */ + CORSAIR_V2_CMD_GET = 0x02, /* Command for getting values */ + CORSAIR_V2_CMD_STOP_TX = 0x05, /* Finish Transaction */ + CORSAIR_V2_CMD_BLK_W1 = 0x06, /* Block write packet 1 */ + CORSAIR_V2_CMD_BLK_WN = 0x07, /* Block write remaining packets */ + CORSAIR_V2_CMD_START_TX = 0x0D, /* Start Transaction */ }; enum corsair_v2_mode { - CORSAIR_V2_MODE_DIRECT = 0x0000, - CORSAIR_V2_MODE_STATIC = 0x207E, - CORSAIR_V2_MODE_FLASHING = 0xAD4F, - CORSAIR_V2_MODE_BREATHING = 0xA5FA, - CORSAIR_V2_MODE_SPECTRUM = 0x7BFF, - CORSAIR_V2_MODE_RAINBOW = 0xB94C, - CORSAIR_V2_MODE_RAIN = 0xA07E, - CORSAIR_V2_MODE_SPIRAL = 0xAB87, - CORSAIR_V2_MODE_WATERCOLOR = 0x0022, - CORSAIR_V2_MODE_REACTIVE = 0xB1F9, - CORSAIR_V2_MODE_RIPPLE = 0x09A2, - CORSAIR_V2_MODE_VISOR = 0x90C0 + CORSAIR_V2_MODE_DIRECT = 0x0012, + CORSAIR_V2_MODE_STATIC = 0x207E, + CORSAIR_V2_MODE_FLASHING = 0xAD4F, + CORSAIR_V2_MODE_BREATHING = 0xA5FA, + CORSAIR_V2_MODE_SPECTRUM = 0x7BFF, + CORSAIR_V2_MODE_RAINBOW = 0xB94C, + CORSAIR_V2_MODE_RAIN = 0xA07E, + CORSAIR_V2_MODE_SPIRAL = 0xAB87, + CORSAIR_V2_MODE_WATERCOLOR = 0x0022, + CORSAIR_V2_MODE_REACTIVE = 0xB1F9, + CORSAIR_V2_MODE_RIPPLE = 0x09A2, + CORSAIR_V2_MODE_VISOR = 0x90C0 }; enum corsair_v2_color { - CORSAIR_V2_COLOR_NONE = 0x00, - CORSAIR_V2_COLOR_SPECIFIC = 0x01, - CORSAIR_V2_COLOR_RANDOM = 0x02, - CORSAIR_V2_COLOR_UNKNOWN = 0x03 + CORSAIR_V2_COLOR_NONE = 0x00, + CORSAIR_V2_COLOR_SPECIFIC = 0x01, + CORSAIR_V2_COLOR_RANDOM = 0x02, + CORSAIR_V2_COLOR_UNKNOWN = 0x03 }; @@ -80,6 +82,11 @@ public: uint8_t direction, uint8_t brightness, std::vector colors); virtual void SetLedsDirect(std::vector colors) = 0; + +protected: + uint16_t device_index; + std::string device_name; + private: void GetAddress(uint8_t address); void StartTransaction(uint8_t opt1); @@ -87,9 +94,7 @@ private: hid_device* dev; - uint8_t write_cmd; - uint16_t device_index; + uint8_t write_cmd = CORSAIR_V2_WRITE_WIRED_ID; std::string firmware_version; std::string location; - std::string device_name; }; diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp index 06b2945e7..767e73a1d 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp @@ -10,6 +10,7 @@ | Corsair Peripheral specific includes | \*-----------------------------------------------------*/ #include "CorsairPeripheralV2Devices.h" +#include "RGBController_CorsairV2Hardware.h" #include "RGBController_CorsairV2Software.h" #define CORSAIR_PERIPHERAL_CONTROLLER_NAME "Corsair V2 Peripheral" @@ -19,6 +20,19 @@ \*-----------------------------------------------------*/ #define CORSAIR_VID 0x1B1C +void DetectCorsairV2HardwareControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + CorsairPeripheralV2HWController* controller = new CorsairPeripheralV2HWController(dev, info->path, name, info->product_id); + RGBController_CorsairV2HW* rgb_controller = new RGBController_CorsairV2HW(controller); + rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} /* DetectCorsairV2SoftwareControllers() */ + void DetectCorsairV2SoftwareControllers(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); @@ -41,10 +55,11 @@ REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO", DetectCorsairV2S REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO Low Profile", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_LP_PID, 1, 0xFF42); /*-----------------------------------------------------------------------------------------------------*\ -| Mousemat | +| Mice | \*-----------------------------------------------------------------------------------------------------*/ REGISTER_HID_DETECTOR_IP("Corsair Ironclaw Wireless", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_IRONCLAW_WIRELESS_PID, 1, 0xFF42); REGISTER_HID_DETECTOR_IP("Corsair Ironclaw Wireless (Wired)", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_IRONCLAW_WIRELESS_WIRED_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair M55 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_M55_RGB_PRO_PID, 1, 0xFF42); /*-----------------------------------------------------------------------------------------------------*\ | Mousemat | diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp index d88ff6aad..c127c08b2 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp @@ -176,7 +176,7 @@ static const corsair_v2_device ironclaw_wired_device = CORSAIR_IRONCLAW_WIRELESS_WIRED_PID, false, DEVICE_TYPE_MOUSE, - CORSAIR_V2_MODE_SW, + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 1, 6, { @@ -196,7 +196,7 @@ static const corsair_v2_device ironclaw_wireless_device = CORSAIR_IRONCLAW_WIRELESS_PID, true, DEVICE_TYPE_MOUSE, - CORSAIR_V2_MODE_SW, + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 1, 6, { @@ -231,7 +231,7 @@ static const corsair_v2_device k55_rgb_pro_device = CORSAIR_K55_RGB_PRO_PID, false, DEVICE_TYPE_KEYBOARD, - CORSAIR_V2_MODE_SW, + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 1, 6, { @@ -266,7 +266,7 @@ static const corsair_v2_device k60_rgb_pro_device = CORSAIR_K60_RGB_PRO_PID, false, DEVICE_TYPE_KEYBOARD, - CORSAIR_V2_MODE_SW, + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 6, 21, { @@ -301,7 +301,7 @@ static const corsair_v2_device k60_rgb_pro_lp_device = CORSAIR_K60_RGB_PRO_LP_PID, false, DEVICE_TYPE_KEYBOARD, - CORSAIR_V2_MODE_SW, + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 6, 21, { @@ -316,6 +316,52 @@ static const corsair_v2_device k60_rgb_pro_lp_device = K60_KEYMAP_SIZE }; +/*-------------------------------------------------------------*\ +| Corsair M55 1B1C:1B70 | +| | +| Zone "Logo" | +| Single | +| | +| Zone "Edge" | +| Linear | +| 1 Row, 2 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone m55_mid_zone = +{ + "Middle Button", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone m55_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_device m55_device = +{ + CORSAIR_M55_RGB_PRO_PID, + false, + DEVICE_TYPE_MOUSE, + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, + 1, + 2, + { + &m55_mid_zone, + &m55_logo_zone, + nullptr, + nullptr, + nullptr, + nullptr + }, + nullptr, + 0 +}; + /*-------------------------------------------------------------*\ | Corsair MM700 1B1C:1B9B | | | @@ -355,7 +401,7 @@ static const corsair_v2_device mm700_device = CORSAIR_MM700_PID, false, DEVICE_TYPE_MOUSEMAT, - CORSAIR_V2_MODE_SW, + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 1, 3, { @@ -387,6 +433,7 @@ const corsair_v2_device* corsair_v2_device_list_data[] = \*-----------------------------------------------------------------*/ &ironclaw_wired_device, &ironclaw_wireless_device, + &m55_device, /*-----------------------------------------------------------------*\ | MOUSEMATS | diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h index e26aa5de3..a76e060d3 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h @@ -12,6 +12,14 @@ enum corsair_v2_device_mode CORSAIR_V2_MODE_SW = 0x02, /* Software RGB mode */ }; +enum corsair_v2_supports +{ + CORSAIR_V2_TYPE_SW_COLOUR_BLOCK = 1, + CORSAIR_V2_TYPE_HW_COLOUR_BLOCK = 2, + CORSAIR_V2_TYPE_SW_TRIPLETS = 3, + CORSAIR_V2_TYPE_HW_TRIPLETS = 4, +}; + typedef struct { std::string name; @@ -34,7 +42,7 @@ typedef struct uint16_t pid; bool wireless; device_type type; - uint8_t supports; + corsair_v2_supports protocol; uint8_t rows; uint8_t cols; const corsair_v2_zone* zones[CORSAIR_ZONES_MAX]; @@ -54,6 +62,7 @@ typedef struct \*-----------------------------------------------------*/ #define CORSAIR_IRONCLAW_WIRELESS_PID 0x1BA6 #define CORSAIR_IRONCLAW_WIRELESS_WIRED_PID 0x1B4C +#define CORSAIR_M55_RGB_PRO_PID 0x1B70 /*-----------------------------------------------------*\ | Corsair V2 Protocol Mousemats | diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp new file mode 100644 index 000000000..c13db697b --- /dev/null +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------*\ +| CorsairPeripheralV2HardwareController.cpp | +| | +| Driver for the newer Corsair peripherals that use the '08' | +| based USB protocol and support hardware lighting modes. | +| | +| Chris M (Dr_No) 07 Dec 2022 | +\*---------------------------------------------------------------------*/ + +#include "LogManager.h" +#include "CorsairPeripheralV2HardwareController.h" + +CorsairPeripheralV2HWController::CorsairPeripheralV2HWController(hid_device* dev_handle, const char* path, std::string name, uint16_t pid) : CorsairPeripheralV2Controller(dev_handle, path, name, pid) +{ + SetRenderMode(CORSAIR_V2_MODE_SW); + LightingControl(0x5F, 0x00); +} + +CorsairPeripheralV2HWController::~CorsairPeripheralV2HWController() +{ + +} + +void CorsairPeripheralV2HWController::SetLedsDirect(std::vectorcolors) +{ + switch(corsair_v2_device_list[device_index]->protocol) + { + case CORSAIR_V2_TYPE_HW_TRIPLETS: + SetLedsDirectTriplets(colors); + break; + case CORSAIR_V2_TYPE_HW_COLOUR_BLOCK: + SetLedsDirectColourBlocks(colors); + break; + default: + LOG_ERROR("[%s] Error setting Direct mode: Device supportes returned %i", device_name.c_str(), + corsair_v2_device_list[device_index]->protocol); + break; + } +} + +void CorsairPeripheralV2HWController::SetLedsDirectColourBlocks(std::vectorcolors) +{ + uint16_t count = colors.size(); + uint16_t green = count + CORSAIR_V2HW_DATA_OFFSET; + uint16_t blue = (count * 2) + CORSAIR_V2HW_DATA_OFFSET; + uint16_t length = (count * 3) + CORSAIR_V2HW_DATA_OFFSET; + uint8_t* buffer = new uint8_t[length]; + + memset(buffer, 0, length); + + buffer[0] = CORSAIR_V2_MODE_DIRECT & 0xFF; + buffer[1] = CORSAIR_V2_MODE_DIRECT >> 8; + for(std::size_t i = 0; i < count; i++) + { + RGBColor color = *colors[i]; + std::size_t idx = i + CORSAIR_V2HW_DATA_OFFSET; + + buffer[idx] = RGBGetRValue(color); + buffer[idx + green] = RGBGetGValue(color); + buffer[idx + blue] = RGBGetBValue(color); + } + + SetLEDs(buffer, length); + delete[] buffer; +} + +void CorsairPeripheralV2HWController::SetLedsDirectTriplets(std::vectorcolors) +{ + uint16_t count = colors.size(); + uint16_t length = (count * 3) + CORSAIR_V2HW_DATA_OFFSET; + uint8_t* buffer = new uint8_t[length]; + + memset(buffer, 0, length); + + buffer[0] = CORSAIR_V2_MODE_DIRECT & 0xFF; + buffer[1] = CORSAIR_V2_MODE_DIRECT >> 8; + for(std::size_t i = 0; i < count; i++) + { + RGBColor color = *colors[i]; + std::size_t idx = (i * 3) + CORSAIR_V2HW_DATA_OFFSET; + + buffer[idx] = RGBGetRValue(color); + buffer[idx + 1] = RGBGetGValue(color); + buffer[idx + 2] = RGBGetBValue(color); + } + + SetLEDs(buffer, length); + delete[] buffer; +} diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h new file mode 100644 index 000000000..d8011698e --- /dev/null +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------*\ +| CorsairPeripheralV2HardwareController.h | +| | +| Driver for the newer Corsair peripherals that use the '08' | +| based USB protocol and support hardware lighting modes. | +| | +| Chris M (Dr_No) 07 Dec 2022 | +\*---------------------------------------------------------------------*/ +#pragma once + +#include "RGBController.h" +#include "CorsairPeripheralV2Controller.h" + +#include +#include + +#undef CORSAIR_V2_WRITE_SIZE +#define CORSAIR_V2_WRITE_SIZE 1025 +#define CORSAIR_V2HW_DATA_OFFSET 2 + +class CorsairPeripheralV2HWController : public CorsairPeripheralV2Controller +{ +public: + CorsairPeripheralV2HWController(hid_device* dev_handle, const char* path, std::string name, uint16_t pid); + ~CorsairPeripheralV2HWController(); + + void SetLedsDirect(std::vector colors); + +private: + void SetLedsDirectColourBlocks(std::vector colors); + void SetLedsDirectTriplets(std::vector colors); +}; diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp new file mode 100644 index 000000000..dcba9e8a4 --- /dev/null +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------*\ +| RGBController_CorsairV2HardwareController.cpp | +| | +| Driver for the newer Corsair peripherals that use the '08' | +| based USB protocol and support hardware lighting modes. | +| | +| Chris M (Dr_No) 10 Dec 2022 | +\*---------------------------------------------------------------------*/ +#include "LogManager.h" +#include "RGBController_CorsairV2Hardware.h" + +using namespace std::chrono_literals; + +/**------------------------------------------------------------------*\ + @name Corsair Peripherals V2 Hardware + @category Keyboard + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectCorsairV2HardwareControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_CorsairV2HW::RGBController_CorsairV2HW(CorsairPeripheralV2Controller *controller_ptr) +{ + controller = controller_ptr; + const corsair_v2_device* corsair = controller->GetDeviceData(); + + vendor = "Corsair"; + description = controller->GetName(); + type = corsair->type; + version = controller->GetFirmwareString(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = CORSAIR_V2_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Static; + Static.name = "Static"; + Static.value = CORSAIR_V2_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(Static.colors_max); + Static.brightness_min = CORSAIR_V2_BRIGHTNESS_MIN; + Static.brightness_max = CORSAIR_V2_BRIGHTNESS_MAX; + Static.brightness = CORSAIR_V2_BRIGHTNESS_MAX; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Static); + + SetupZones(); + /*-----------------------------------------------------*\ + | The Corsair K55 RGB PRO requires a packet within | + | 1 minutes of sending the lighting change in order | + | to not revert back into rainbow mode. Start a thread | + | to continuously send a keepalive packet every 50 sec | + \*-----------------------------------------------------*/ + keepalive_thread_run = true; + keepalive_thread = new std::thread(&RGBController_CorsairV2HW::KeepaliveThread, this); +} + +RGBController_CorsairV2HW::~RGBController_CorsairV2HW() +{ + /*-----------------------------------------------------*\ + | Close keepalive thread | + \*-----------------------------------------------------*/ + keepalive_thread_run = false; + keepalive_thread->join(); + delete keepalive_thread; + + /*---------------------------------------------------------*\ + | Delete the matrix map | + \*---------------------------------------------------------*/ + for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) + { + if(zones[zone_index].type == ZONE_TYPE_MATRIX) + { + delete zones[zone_index].matrix_map; + } + } + + delete controller; +} + +void RGBController_CorsairV2HW::SetupZones() +{ + unsigned int max_led_value = 0; + const corsair_v2_device* corsair = controller->GetDeviceData(); + + /*---------------------------------------------------------*\ + | Fill in zones from the device data | + \*---------------------------------------------------------*/ + for(size_t i = 0; i < CORSAIR_ZONES_MAX; i++) + { + if(corsair->zones[i] == NULL) + { + break; + } + else + { + zone new_zone; + + new_zone.name = corsair->zones[i]->name; + new_zone.type = corsair->zones[i]->type; + + if(new_zone.type == ZONE_TYPE_MATRIX) + { + new_zone.leds_count = corsair->layout_size; + matrix_map_type * new_map = new matrix_map_type; + new_zone.matrix_map = new_map; + + new_map->height = corsair->zones[i]->rows; + new_map->width = corsair->zones[i]->cols; + + new_map->map = new unsigned int[new_map->height * new_map->width]; + + /*---------------------------------------------------------*\ + | Create an empty matrix | + \*---------------------------------------------------------*/ + for(unsigned int y = 0; y < new_map->height; y++) + { + for(unsigned int x = 0; x < new_map->width; x++) + { + new_map->map[(y * new_map->width) + x] = NA; + } + } + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + for(size_t led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = corsair->layout[led_idx].name; + new_led.value = corsair->layout[led_idx].index; + max_led_value = std::max(max_led_value, new_led.value); + leds.push_back(new_led); + + uint8_t layout_index = (corsair->layout[led_idx].row * new_map->width) + + corsair->layout[led_idx].col; + new_map->map[layout_index] = led_idx; + } + + /*---------------------------------------------------------*\ + | Add 1 the max_led_value to account for the 0th index | + \*---------------------------------------------------------*/ + max_led_value++; + } + else + { + new_zone.leds_count = corsair->zones[i]->rows * corsair->zones[i]->cols; + new_zone.matrix_map = NULL; + + /*---------------------------------------------------------*\ + | Create LEDs for the Linear / Single zone | + \*---------------------------------------------------------*/ + for(size_t led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = new_zone.name + " "; + new_led.name.append(std::to_string( led_idx )); + new_led.value = leds.size(); + + leds.push_back(new_led); + } + + max_led_value = std::max(max_led_value, (unsigned int)leds.size()); + } + + LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", name.c_str(), + ((new_zone.type == ZONE_TYPE_MATRIX) ? "matrix": "linear"), + new_zone.name.c_str(), new_zone.leds_count); + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + zones.push_back(new_zone); + } + } + + SetupColors(); + + /*---------------------------------------------------------*\ + | Create a buffer map of pointers which contains the | + | layout order of colors the device expects. | + \*---------------------------------------------------------*/ + for(size_t led_idx = 0; led_idx < max_led_value; led_idx++) + { + buffer_map.push_back(&null_color); + } + + for(size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + buffer_map[leds[led_idx].value] = &colors[led_idx]; + } +} + +void RGBController_CorsairV2HW::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_CorsairV2HW::DeviceUpdateLEDs() +{ + last_update_time = std::chrono::steady_clock::now(); + + controller->SetLedsDirect(buffer_map); +} + +void RGBController_CorsairV2HW::UpdateZoneLEDs(int /*zone*/) +{ + controller->SetLedsDirect(buffer_map); +} + +void RGBController_CorsairV2HW::UpdateSingleLED(int /*led*/) +{ + controller->SetLedsDirect(buffer_map); +} + +void RGBController_CorsairV2HW::DeviceUpdateMode() +{ + +} + +void RGBController_CorsairV2HW::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if(active_mode == 0) + { + if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50000)) + { + DeviceUpdateLEDs(); + } + } + std::this_thread::sleep_for(30000ms); + } +} diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h new file mode 100644 index 000000000..d6cff4a2d --- /dev/null +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------*\ +| RGBController_CorsairV2HardwareController.h | +| | +| Driver for the newer Corsair peripherals that use the '08' | +| based USB protocol and support hardware lighting modes. | +| | +| Chris M (Dr_No) 10 Dec 2022 | +\*---------------------------------------------------------------------*/ +#pragma once + +#include "RGBController.h" +#include "CorsairPeripheralV2Controller.h" +#include "CorsairPeripheralV2HardwareController.h" + +class RGBController_CorsairV2HW : public RGBController +{ +public: + RGBController_CorsairV2HW(CorsairPeripheralV2Controller* controller_ptr); + ~RGBController_CorsairV2HW(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void KeepaliveThread(); + +private: + CorsairPeripheralV2Controller* controller; + + RGBColor null_color = 0; + std::vector buffer_map; + + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point + last_update_time; + +}; diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp index 83c4ee48a..19807e17f 100644 --- a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp @@ -13,7 +13,7 @@ using namespace std::chrono_literals; /**------------------------------------------------------------------*\ - @name Corsair K55 RGB Pro + @name Corsair Peripherals V2 Software @category Keyboard @type USB @save :x: @@ -35,7 +35,7 @@ RGBController_CorsairV2SW::RGBController_CorsairV2SW(CorsairPeripheralV2Controll location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - if(corsair->supports & CORSAIR_V2_MODE_SW) + if(corsair->protocol & CORSAIR_V2_TYPE_SW_COLOUR_BLOCK) { mode Direct; Direct.name = "Direct"; @@ -43,10 +43,7 @@ RGBController_CorsairV2SW::RGBController_CorsairV2SW(CorsairPeripheralV2Controll Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); - } - if(corsair->supports & CORSAIR_V2_MODE_HW) - { mode Static; Static.name = "Static"; Static.value = CORSAIR_V2_MODE_STATIC; @@ -249,6 +246,6 @@ void RGBController_CorsairV2SW::KeepaliveThread() DeviceUpdateLEDs(); } } - std::this_thread::sleep_for(3000ms); + std::this_thread::sleep_for(30000ms); } } diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h index 702d7118f..c594ecebd 100644 --- a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h @@ -10,6 +10,7 @@ #include "RGBController.h" #include "CorsairPeripheralV2Controller.h" +#include "CorsairPeripheralV2HardwareController.h" #include "CorsairPeripheralV2SoftwareController.h" class RGBController_CorsairV2SW : public RGBController diff --git a/OpenRGB.pro b/OpenRGB.pro index 2b735af41..6b603996d 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -355,7 +355,9 @@ HEADERS += Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.h \ Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h \ Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h \ + Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h \ Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.h \ + Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h \ Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h \ Controllers/CorsairVengeanceController/CorsairVengeanceController.h \ Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.h \ @@ -908,7 +910,9 @@ SOURCES += Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp \ Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp \ Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp \ + Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp \ Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.cpp \ + Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp \ Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp \ Controllers/CorsairVengeanceController/CorsairVengeanceController.cpp \ Controllers/CorsairVengeanceController/CorsairVengeanceControllerDetect.cpp \