From d3a36fc1840a6134074e938ae53edeabe8cce37d Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Sun, 7 Jun 2020 13:46:31 -0500 Subject: [PATCH] FanController implementation for Corsair Commander Pro --- .../CorsairLightingNodeController.cpp | 147 ++++++++++++++++++ .../CorsairLightingNodeController.h | 46 ++++++ .../CorsairLightingNodeControllerDetect.cpp | 119 +++++++------- .../FanController_CorsairCommander.cpp | 57 +++++++ .../FanController_CorsairCommander.h | 24 +++ 5 files changed, 338 insertions(+), 55 deletions(-) create mode 100644 Controllers/CorsairLightingNodeController/FanController_CorsairCommander.cpp create mode 100644 Controllers/CorsairLightingNodeController/FanController_CorsairCommander.h diff --git a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp index 026fb78f..cf4a3f8a 100644 --- a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp +++ b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp @@ -59,6 +59,70 @@ void CorsairLightingNodeController::KeepaliveThread() } } +unsigned char CorsairLightingNodeController::GetFanPercent(unsigned char fan_channel) +{ + int actual; + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Get Fan RPM packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = CORSAIR_LIGHTING_NODE_PACKET_ID_GET_FAN_PERCENT; + usb_buf[0x01] = fan_channel; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); + actual = hid_read(dev, usb_buf, 16); + + if(actual > 0) + { + return(usb_buf[0x01]); + } + else + { + return(0); + } +} + +unsigned short CorsairLightingNodeController::GetFanRPM(unsigned char fan_channel) +{ + int actual; + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Get Fan RPM packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = CORSAIR_LIGHTING_NODE_PACKET_ID_GET_FAN_RPM; + usb_buf[0x01] = fan_channel; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); + actual = hid_read(dev, usb_buf, 16); + + if(actual > 0) + { + return((usb_buf[0x01] << 8) + (usb_buf[0x02] & 0xFF)); + } + else + { + return(0); + } +} + std::string CorsairLightingNodeController::GetFirmwareString() { return(firmware_version); @@ -203,6 +267,89 @@ void CorsairLightingNodeController::SetChannelLEDs(unsigned char channel, RGBCol SendCommit(); } +void CorsairLightingNodeController::SetFanConfiguration + ( + unsigned char fan_channel, + unsigned char fan_configuration + ) +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Fan Configuration packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CONFIG; + usb_buf[0x01] = 0x02; + usb_buf[0x02] = fan_channel; + usb_buf[0x03] = fan_configuration; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); + hid_read(dev, usb_buf, 16); +} + +void CorsairLightingNodeController::SetFanPercent + ( + unsigned char fan_channel, + unsigned char fan_cmd + ) +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Fan Fixed Percent Command packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CMD_PERCENT; + usb_buf[0x01] = fan_channel; + usb_buf[0x02] = fan_cmd; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); + hid_read(dev, usb_buf, 16); +} + +void CorsairLightingNodeController::SetFanRPM + ( + unsigned char fan_channel, + unsigned short fan_cmd + ) +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Fan Fixed RPM Command packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CMD_RPM; + usb_buf[0x01] = fan_channel; + usb_buf[0x02] = fan_cmd & 0xFF; + usb_buf[0x03] = fan_cmd >> 8; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); + hid_read(dev, usb_buf, 16); +} + /*-------------------------------------------------------------------------------------------------*\ | Private packet sending functions. | \*-------------------------------------------------------------------------------------------------*/ diff --git a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h index b7694f3b..17960be9 100644 --- a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h +++ b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h @@ -23,6 +23,12 @@ enum { CORSAIR_LIGHTING_NODE_PACKET_ID_FIRMWARE = 0x02, /* Get firmware version */ + CORSAIR_LIGHTING_NODE_PACKET_ID_GET_FAN_CONFIG = 0x20, /* Get fan configuration */ + CORSAIR_LIGHTING_NODE_PACKET_ID_GET_FAN_RPM = 0x21, /* Get fan RPM */ + CORSAIR_LIGHTING_NODE_PACKET_ID_GET_FAN_PERCENT = 0x22, /* Get fan fixed percent command */ + CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CMD_PERCENT = 0x23, /* Set fan fixed percent command */ + CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CMD_RPM = 0x24, /* Set fan fixed RPM command */ + CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CONFIG = 0x28, /* Set fan configuration */ CORSAIR_LIGHTING_NODE_PACKET_ID_DIRECT = 0x32, /* Direct mode LED update packet */ CORSAIR_LIGHTING_NODE_PACKET_ID_COMMIT = 0x33, /* Commit changes packet */ CORSAIR_LIGHTING_NODE_PACKET_ID_BEGIN = 0x34, /* Begin effect packet */ @@ -63,6 +69,17 @@ enum CORSAIR_LIGHTING_NODE_NUM_CHANNELS = 0x02, /* Number of channels */ }; +enum +{ + CORSAIR_LIGHTING_NODE_FAN_CHANNEL_1 = 0x00, /* Fan channel 1 */ + CORSAIR_LIGHTING_NODE_FAN_CHANNEL_2 = 0x01, /* Fan channel 2 */ + CORSAIR_LIGHTING_NODE_FAN_CHANNEL_3 = 0x02, /* Fan channel 3 */ + CORSAIR_LIGHTING_NODE_FAN_CHANNEL_4 = 0x03, /* Fan channel 4 */ + CORSAIR_LIGHTING_NODE_FAN_CHANNEL_5 = 0x04, /* Fan channel 5 */ + CORSAIR_LIGHTING_NODE_FAN_CHANNEL_6 = 0x05, /* Fan channel 6 */ + CORSAIR_LIGHTING_NODE_NUM_FAN_CHANNELS = 0x06, /* Number of fan channels */ +}; + enum { CORSAIR_LIGHTING_NODE_SPEED_FAST = 0x00, /* Fast speed */ @@ -85,12 +102,23 @@ enum CORSAIR_LIGHTING_NODE_MODE_RAINBOW = 0x0A, /* Rainbow mode */ }; +enum +{ + CORSAIR_LIGHTING_NODE_FAN_CONFIG_AUTO = 0x00, /* Auto/Disconnected */ + CORSAIR_LIGHTING_NODE_FAN_CONFIG_3_PIN = 0x01, /* 3-Pin Fan */ + CORSAIR_LIGHTING_NODE_FAN_CONFIG_4_PIN = 0x02, /* 4-Pin Fan */ +}; + class CorsairLightingNodeController { public: CorsairLightingNodeController(hid_device* dev_handle, const char* path); ~CorsairLightingNodeController(); + unsigned char GetFanPercent(unsigned char fan_channel); + + unsigned short GetFanRPM(unsigned char fan_channel); + std::string GetFirmwareString(); std::string GetLocationString(); std::string GetSerialString(); @@ -118,6 +146,24 @@ public: void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + void SetFanConfiguration + ( + unsigned char fan_channel, + unsigned char fan_configuration + ); + + void SetFanPercent + ( + unsigned char fan_channel, + unsigned char fan_cmd + ); + + void SetFanRPM + ( + unsigned char fan_channel, + unsigned short fan_cmd + ); + void KeepaliveThread(); private: diff --git a/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp b/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp index 2e7112be..9246f5ab 100644 --- a/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp +++ b/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp @@ -1,55 +1,64 @@ -/*---------------------------------------------------------*\ -| CorsairLightingNodeControllerDetect.cpp | -| | -| Detector for Corsair Lighting Node devices | -| | -| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2020 | -| | -| This file is part of the OpenRGB project | -| SPDX-License-Identifier: GPL-2.0-only | -\*---------------------------------------------------------*/ - -#include -#include -#include "Detector.h" -#include "CorsairLightingNodeController.h" -#include "RGBController.h" -#include "RGBController_CorsairLightingNode.h" - -#define CORSAIR_VID 0x1B1C -#define CORSAIR_LIGHTING_NODE_CORE_PID 0x0C1A -#define CORSAIR_LIGHTING_NODE_PRO_PID 0x0C0B -#define CORSAIR_COMMANDER_PRO_PID 0x0C10 -#define CORSAIR_LS100_PID 0x0C1E -#define CORSAIR_1000D_OBSIDIAN_PID 0x1D00 -#define CORSAIR_SPEC_OMEGA_RGB_PID 0x1D04 -#define CORSAIR_LT100_PID 0x0C23 - -/******************************************************************************************\ -* * -* DetectCorsairLightingNodeControllers * -* * -* Detect devices supported by the Corsair Lighting Node Pro driver * -* * -\******************************************************************************************/ - -void DetectCorsairLightingNodeControllers(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - - if(dev) - { - CorsairLightingNodeController* controller = new CorsairLightingNodeController(dev, info->path); - RGBController_CorsairLightingNode* rgb_controller = new RGBController_CorsairLightingNode(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} /* DetectCorsairLightingNodeControllers() */ - -REGISTER_HID_DETECTOR("Corsair Lighting Node Core", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LIGHTING_NODE_CORE_PID); // 1 channel -REGISTER_HID_DETECTOR("Corsair Lighting Node Pro", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LIGHTING_NODE_PRO_PID); // 2 channels -REGISTER_HID_DETECTOR("Corsair Commander Pro", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_COMMANDER_PRO_PID); // 2 channels -REGISTER_HID_DETECTOR("Corsair LS100 Lighting Kit", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LS100_PID); // 1 channel -REGISTER_HID_DETECTOR("Corsair 1000D Obsidian", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_1000D_OBSIDIAN_PID); // 2 channels -REGISTER_HID_DETECTOR("Corsair SPEC OMEGA RGB", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_SPEC_OMEGA_RGB_PID); // 2 channels -REGISTER_HID_DETECTOR("Corsair LT100", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LT100_PID); // 2 channels +/*---------------------------------------------------------*\ +| CorsairLightingNodeControllerDetect.cpp | +| | +| Detector for Corsair Lighting Node devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "Detector.h" +#include "CorsairLightingNodeController.h" +#include "FanController.h" +#include "FanController_CorsairCommander.h" +#include "RGBController.h" +#include "RGBController_CorsairLightingNode.h" + +#define CORSAIR_VID 0x1B1C +#define CORSAIR_LIGHTING_NODE_CORE_PID 0x0C1A +#define CORSAIR_LIGHTING_NODE_PRO_PID 0x0C0B +#define CORSAIR_COMMANDER_PRO_PID 0x0C10 +#define CORSAIR_LS100_PID 0x0C1E +#define CORSAIR_1000D_OBSIDIAN_PID 0x1D00 +#define CORSAIR_SPEC_OMEGA_RGB_PID 0x1D04 +#define CORSAIR_LT100_PID 0x0C23 + +/******************************************************************************************\ +* * +* DetectCorsairLightingNodeControllers * +* * +* Detect devices supported by the Corsair Lighting Node Pro driver * +* * +\******************************************************************************************/ + +void DetectCorsairLightingNodeControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + CorsairLightingNodeController* controller = new CorsairLightingNodeController(dev, info->path); + RGBController_CorsairLightingNode* rgb_controller = new RGBController_CorsairLightingNode(controller); + rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); + + if(info->product_id == CORSAIR_COMMANDER_PRO_PID) + { + FanController_CorsairCommander* fan_controller = new FanController_CorsairCommander(controller); + fan_controller->name = name; + ResourceManager::get()->RegisterFanController(fan_controller); + } + } +} /* DetectCorsairLightingNodeControllers() */ + +REGISTER_HID_DETECTOR("Corsair Lighting Node Core", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LIGHTING_NODE_CORE_PID); // 1 channel +REGISTER_HID_DETECTOR("Corsair Lighting Node Pro", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LIGHTING_NODE_PRO_PID); // 2 channels +REGISTER_HID_DETECTOR("Corsair Commander Pro", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_COMMANDER_PRO_PID); // 2 channels +REGISTER_HID_DETECTOR("Corsair LS100 Lighting Kit", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LS100_PID); // 1 channel +REGISTER_HID_DETECTOR("Corsair 1000D Obsidian", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_1000D_OBSIDIAN_PID); // 2 channels +REGISTER_HID_DETECTOR("Corsair SPEC OMEGA RGB", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_SPEC_OMEGA_RGB_PID); // 2 channels +REGISTER_HID_DETECTOR("Corsair LT100", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LT100_PID); // 2 channels diff --git a/Controllers/CorsairLightingNodeController/FanController_CorsairCommander.cpp b/Controllers/CorsairLightingNodeController/FanController_CorsairCommander.cpp new file mode 100644 index 00000000..cf4ed59a --- /dev/null +++ b/Controllers/CorsairLightingNodeController/FanController_CorsairCommander.cpp @@ -0,0 +1,57 @@ +/*-----------------------------------------*\ +| FanController_CorsairCommander.cpp | +| | +| Generic Fan Interface for Corsair | +| Commander controller | +| | +| Adam Honse (CalcProgrammer1) 6/7/2020 | +\*-----------------------------------------*/ + +#include "FanController_CorsairCommander.h" + +FanController_CorsairCommander::FanController_CorsairCommander(CorsairLightingNodeController* corsair_ptr) +{ + corsair = corsair_ptr; + + name = "Corsair Commander"; + description = "Corsair Commander Device"; + version = corsair->GetFirmwareString(); + + for(std::size_t fan_index = 0; fan_index < CORSAIR_LIGHTING_NODE_NUM_FAN_CHANNELS; fan_index++) + { + fan new_fan; + + new_fan.name = "Corsair Commander Fan "; + new_fan.name.append(std::to_string(fan_index + 1)); + new_fan.speed_min = 0; + new_fan.speed_max = 100; + new_fan.speed_cmd = corsair->GetFanPercent(fan_index); + new_fan.rpm_rdg = corsair->GetFanRPM(fan_index); + + fans.push_back(new_fan); + + corsair->SetFanConfiguration(fan_index, CORSAIR_LIGHTING_NODE_FAN_CONFIG_4_PIN); + } + + UpdateControl(); +} + +void FanController_CorsairCommander::UpdateControl() +{ + for(std::size_t fan_index = 0; fan_index < fans.size(); fan_index++) + { + corsair->SetFanPercent(fan_index, fans[fan_index].speed_cmd); + } +} + +void FanController_CorsairCommander::UpdateReading() +{ + for(std::size_t fan_index = 0; fan_index < fans.size(); fan_index++) + { + unsigned short rpm; + + rpm = corsair->GetFanRPM(fan_index); + + fans[fan_index].rpm_rdg = rpm; + } +} \ No newline at end of file diff --git a/Controllers/CorsairLightingNodeController/FanController_CorsairCommander.h b/Controllers/CorsairLightingNodeController/FanController_CorsairCommander.h new file mode 100644 index 00000000..862b317c --- /dev/null +++ b/Controllers/CorsairLightingNodeController/FanController_CorsairCommander.h @@ -0,0 +1,24 @@ +/*-----------------------------------------*\ +| FanController_CorsairCommander.h | +| | +| Generic Fan Interface for Corsair | +| Commander controller | +| | +| Adam Honse (CalcProgrammer1) 6/7/2020 | +\*-----------------------------------------*/ + +#pragma once +#include "FanController.h" +#include "CorsairLightingNodeController.h" + +class FanController_CorsairCommander : public FanController +{ +public: + FanController_CorsairCommander(CorsairLightingNodeController* corsair_ptr); + + void UpdateControl(); + void UpdateReading(); + +private: + CorsairLightingNodeController* corsair; +};