Compare commits

...
Author SHA1 Message Date
Adam Honse 75e1f42c23 Initialize NZXT Hue 2 fan reporting 2024-10-05 17:54:39 -05:00
Dmitry K af23c04007 [FAN Controller] Initial implementation for Asus TUF Fan controller 2024-10-05 16:03:50 -05:00
Adam Honse 779c15e41c Add basic Razer Blade 14 2021 fan control based on razer-fan-control's reverse engineering effort. Commanding zero speed sets auto fan control mode 2024-10-05 16:03:50 -05:00
Scott Wilde a6915868d2 fix fan box initial values 2024-10-05 16:03:50 -05:00
Scott Wilde 7266e4131a Initial commit for KrakenX fan controller
Commits squashed and amended for code style by Adam Honse <[email protected]>
2024-10-05 16:03:50 -05:00
Adam Honse b5105ed096 Add Fan Controller for FanBus Devices 2024-10-05 16:03:49 -05:00
Adam Honse 156cbfab0f More hidapi changes for windows 2024-10-05 16:03:49 -05:00
Adam Honse 289f14214f Fix fan controller UI 2024-10-05 16:03:49 -05:00
Adam Honse 4fc1e84001 Adjust packet sizes for hidapi byte 0 2024-10-05 16:03:49 -05:00
Adam Honse 188d8592ce Join fan update thread before deleting fan tab 2024-10-05 16:03:49 -05:00
Adam Honse 73051af251 Select the main tab by default, not the fan tab 2024-10-05 16:03:49 -05:00
Adam Honse 9a960a7d48 Initial NZXT Smart Device V2 fan controller. Use a thread to process fan updates to avoid locking up the dialog. 2024-10-05 16:03:49 -05:00
Adam Honse d3a36fc184 FanController implementation for Corsair Commander Pro 2024-10-05 16:03:49 -05:00
Adam Honse f995eb8021 Initial fan controller API and Thermaltake Riing controller implementation 2024-10-05 16:03:49 -05:00
43 changed files with 1592 additions and 76 deletions
@@ -9,6 +9,7 @@
#include <string>
#include "Detector.h"
#include "FanController_AsusTUFLaptop_Windows.h"
#include "RGBController_AsusTUFLaptop_Windows.h"
#include "wmi.h"
@@ -44,8 +45,10 @@ static void DetectAsusTUFLaptopWMIControllers()
if(controller)
{
RGBController* new_controller = new RGBController_AsusTUFLaptopWMI(controller);
FanController* fan_controller = new FanController_AsusTUFLaptopWMI(controller);
ResourceManager::get()->RegisterRGBController(new_controller);
ResourceManager::get()->RegisterFanController(fan_controller);
}
} /* DetectAsusTUFLaptopWMIControllers() */
@@ -0,0 +1,44 @@
#include "FanController_AsusTUFLaptop_Windows.h"
FanController_AsusTUFLaptopWMI::FanController_AsusTUFLaptopWMI(AsusTUFLaptopController* dev)
{
controller = dev;
name = "ASUS TUF Laptop";
description = "WMI Device";
location = "\\\\.\\ATKACPI";
// Coolers RPM reading & current mode retrieval is still WIP
fans.resize(2);
fans[0].name = "CPU Cooler";
fans[0].speed_min = 0;
fans[0].speed_max = 2;
fans[0].speed_cmd = 1;
fans[0].prev_speed_cmd = 1;
fans[0].rpm_rdg = 0; // We don't have it, but we don't want an unitialized value either
}
void FanController_AsusTUFLaptopWMI::UpdateControl()
{
int mode = fans[0].speed_cmd;
switch(mode)
{
case 0:
mode = ASUS_WMI_FAN_SPEED_SILENT;
break;
case 1:
mode = ASUS_WMI_FAN_SPEED_NORMAL;
break;
case 2:
mode = ASUS_WMI_FAN_SPEED_TURBO;
break;
}
controller->setFanMode(mode);
}
void FanController_AsusTUFLaptopWMI::UpdateReading()
{
;
}
@@ -0,0 +1,18 @@
#ifndef FANCONTROLLER_ASUSTUFLAPTOPWMI_H
#define FANCONTROLLER_ASUSTUFLAPTOPWMI_H
#include "FanController.h"
#include "AsusTUFLaptopController_Windows.h"
class FanController_AsusTUFLaptopWMI : public FanController
{
private:
AsusTUFLaptopController* controller;
public:
FanController_AsusTUFLaptopWMI(AsusTUFLaptopController* dev);
void UpdateControl() override;
void UpdateReading() override;
};
#endif // FANCONTROLLER_ASUSTUFLAPTOPWMI_H
@@ -59,6 +59,72 @@ void CorsairLightingNodeController::KeepaliveThread()
}
}
unsigned char CorsairLightingNodeController::GetFanPercent(unsigned char fan_channel)
{
int actual;
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Get Fan RPM packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_GET_FAN_PERCENT;
usb_buf[0x02] = fan_channel;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
actual = hid_read(dev, usb_buf, 17);
if(actual > 0)
{
return(usb_buf[0x01]);
}
else
{
return(0);
}
}
unsigned short CorsairLightingNodeController::GetFanRPM(unsigned char fan_channel)
{
int actual;
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Get Fan RPM packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_GET_FAN_RPM;
usb_buf[0x02] = fan_channel;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
actual = hid_read(dev, usb_buf, 17);
if(actual > 0)
{
return((usb_buf[0x01] << 8) + (usb_buf[0x02] & 0xFF));
}
else
{
return(0);
}
}
std::string CorsairLightingNodeController::GetFirmwareString()
{
return(firmware_version);
@@ -203,6 +269,92 @@ void CorsairLightingNodeController::SetChannelLEDs(unsigned char channel, RGBCol
SendCommit();
}
void CorsairLightingNodeController::SetFanConfiguration
(
unsigned char fan_channel,
unsigned char fan_configuration
)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Fan Configuration packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CONFIG;
usb_buf[0x02] = 0x02;
usb_buf[0x03] = fan_channel;
usb_buf[0x04] = fan_configuration;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
hid_read(dev, usb_buf, 17);
}
void CorsairLightingNodeController::SetFanPercent
(
unsigned char fan_channel,
unsigned char fan_cmd
)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Fan Fixed Percent Command packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CMD_PERCENT;
usb_buf[0x02] = fan_channel;
usb_buf[0x03] = fan_cmd;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
hid_read(dev, usb_buf, 17);
}
void CorsairLightingNodeController::SetFanRPM
(
unsigned char fan_channel,
unsigned short fan_cmd
)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Fan Fixed RPM Command packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_FAN_CMD_RPM;
usb_buf[0x02] = fan_channel;
usb_buf[0x03] = fan_cmd & 0xFF;
usb_buf[0x04] = fan_cmd >> 8;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
hid_read(dev, usb_buf, 17);
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
@@ -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:
@@ -1,55 +1,64 @@
/*---------------------------------------------------------*\
| CorsairLightingNodeControllerDetect.cpp |
| |
| Detector for Corsair Lighting Node devices |
| |
| Adam Honse ([email protected]) 12 Jan 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include <vector>
#include <hidapi.h>
#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 ([email protected]) 12 Jan 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include <vector>
#include <hidapi.h>
#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
@@ -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;
}
}
@@ -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;
};
@@ -34,6 +34,31 @@ std::string FanBusController::GetLocation()
return(location_string);
}
unsigned char FanBusController::GetFanPWM()
{
unsigned char fan_pwm;
fan_pwm = bus->read(dev, 0x01);
return(fan_pwm);
}
unsigned short FanBusController::GetFanRPM()
{
unsigned char fan_rpm_low;
unsigned char fan_rpm_high;
fan_rpm_low = bus->read(dev, 0x02);
fan_rpm_high = bus->read(dev, 0x03);
return((fan_rpm_high << 8) | fan_rpm_low);
}
void FanBusController::SetFanPWM(unsigned char fan_pwm)
{
bus->write(dev, 0x01, fan_pwm);
}
void FanBusController::SetLEDs(std::vector<RGBColor> colors)
{
for(unsigned int led_idx = 0; led_idx < 4; led_idx++)
@@ -21,9 +21,12 @@ public:
FanBusController(FanBusInterface* bus_ptr, unsigned char dev_addr);
~FanBusController();
std::string GetLocation();
std::string GetLocation();
void SetLEDs(std::vector<RGBColor> colors);
unsigned char GetFanPWM();
unsigned short GetFanRPM();
void SetFanPWM(unsigned char fan_pwm);
void SetLEDs(std::vector<RGBColor> colors);
private:
std::string port_name;
@@ -11,6 +11,7 @@
#include "Detector.h"
#include "FanBusController.h"
#include "FanController_FanBus.h"
#include "RGBController_FanBus.h"
#include "SettingsManager.h"
@@ -45,6 +46,10 @@ void DetectFanBusControllers()
RGBController_FanBus* rgb_controller = new RGBController_FanBus(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
FanController_FanBus* fan_controller = new FanController_FanBus(controller);
ResourceManager::get()->RegisterFanController(fan_controller);
}
}
}
@@ -0,0 +1,43 @@
/*-----------------------------------------*\
| FanController_FanBus.cpp |
| |
| Generic Fan Interface for FanBus |
| controller |
| |
| Adam Honse (CalcProgrammer1) 3/1/2020 |
\*-----------------------------------------*/
#include "FanController_FanBus.h"
FanController_FanBus::FanController_FanBus(FanBusController* controller_ptr)
{
controller = controller_ptr;
name = "FanBus Device";
description = "FanBus Device";
location = controller->GetLocation();
fan new_fan;
new_fan.name = "FanBus Fan";
new_fan.speed_min = 0;
new_fan.speed_max = 255;
new_fan.speed_cmd = controller->GetFanPWM();
new_fan.rpm_rdg = controller->GetFanRPM();
fans.push_back(new_fan);
}
void FanController_FanBus::UpdateControl()
{
controller->SetFanPWM(fans[0].speed_cmd);
}
void FanController_FanBus::UpdateReading()
{
unsigned short rpm;
rpm = controller->GetFanRPM();
fans[0].rpm_rdg = rpm;
}
@@ -0,0 +1,24 @@
/*-----------------------------------------*\
| FanController_FanBus.h |
| |
| Generic Fan Interface for FanBus |
| controller |
| |
| Adam Honse (CalcProgrammer1) 3/1/2020 |
\*-----------------------------------------*/
#pragma once
#include "FanController.h"
#include "FanBusController.h"
class FanController_FanBus : public FanController
{
public:
FanController_FanBus(FanBusController* controller_ptr);
void UpdateControl();
void UpdateReading();
private:
FanBusController* controller;
};
@@ -0,0 +1,55 @@
/*-----------------------------------------*\
| FanController_NZXTHue2.cpp |
| |
| Generic Fan Interface for NZXT Hue 2 |
| (Smart Device V2, Fan & RGB) controller |
| |
| Adam Honse (CalcProgrammer1) 6/22/2020 |
\*-----------------------------------------*/
#include "FanController_NZXTHue2.h"
FanController_NZXTHue2::FanController_NZXTHue2(NZXTHue2Controller* hue2_ptr)
{
hue2 = hue2_ptr;
name = "NZXT Hue 2 Device";
description = "NZXT Hue 2 Device";
version = hue2->GetFirmwareVersion();
for(std::size_t fan_index = 0; fan_index < hue2->GetNumFanChannels(); fan_index++)
{
fan new_fan;
hue2->UpdateStatus();
new_fan.name = "NZXT 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 = hue2->GetFanCommand(fan_index);
new_fan.rpm_rdg = hue2->GetFanRPM(fan_index);
fans.push_back(new_fan);
}
UpdateControl();
}
void FanController_NZXTHue2::UpdateControl()
{
for(std::size_t fan_index = 0; fan_index < fans.size(); fan_index++)
{
hue2->SendFan(fan_index, 0, fans[fan_index].speed_cmd);
}
}
void FanController_NZXTHue2::UpdateReading()
{
hue2->UpdateStatus();
for(std::size_t fan_index = 0; fan_index < fans.size(); fan_index++)
{
fans[fan_index].rpm_rdg = hue2->GetFanRPM(fan_index);
}
}
@@ -0,0 +1,24 @@
/*-----------------------------------------*\
| FanController_NZXTHue2.h |
| |
| Generic Fan Interface for NZXT Hue 2 |
| (Smart Device V2, Fan & RGB) controller |
| |
| Adam Honse (CalcProgrammer1) 6/22/2020 |
\*-----------------------------------------*/
#pragma once
#include "FanController.h"
#include "NZXTHue2Controller.h"
class FanController_NZXTHue2 : public FanController
{
public:
FanController_NZXTHue2(NZXTHue2Controller* hue2_ptr);
void UpdateControl();
void UpdateReading();
private:
NZXTHue2Controller* hue2;
};
@@ -30,6 +30,48 @@ NZXTHue2Controller::NZXTHue2Controller(hid_device* dev_handle, unsigned int rgb_
fan_cmd.resize(num_fan_channels);
fan_rpm.resize(num_fan_channels);
unsigned char usb_buf[64];
unsigned int ret_val = 0;
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Fan Reporting Interval packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x60;
usb_buf[0x01] = 0x02;
usb_buf[0x02] = 0x01;
usb_buf[0x03] = 0xE8;
usb_buf[0x04] = 0x03;
usb_buf[0x05] = 0x01;
usb_buf[0x06] = 0xE8;
usb_buf[0x07] = 0x03;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 64);
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Enable Fan Reporting packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x60;
usb_buf[0x01] = 0x03;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 64);
UpdateStatus();
}
@@ -249,7 +291,7 @@ void NZXTHue2Controller::UpdateStatus()
unsigned char usb_buf[64];
unsigned int ret_val = 0;
if(false)//num_fan_channels > 0)
if(num_fan_channels > 0)
{
/*-----------------------------------------------------*\
| Zero out buffer |
@@ -12,6 +12,8 @@
#include <hidapi.h>
#include "Detector.h"
#include "NZXTHue2Controller.h"
#include "FanController.h"
#include "FanController_NZXTHue2.h"
#include "RGBController.h"
#include "RGBController_NZXTHue2.h"
@@ -45,6 +47,13 @@ static void spawn_hue(hid_device_info* info, const std::string& name, int rgb_ch
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
if(fan_channels > 0)
{
FanController_NZXTHue2* fan_controller = new FanController_NZXTHue2(controller);
fan_controller->name = name;
ResourceManager::get()->RegisterFanController(fan_controller);
}
}
}
@@ -0,0 +1,71 @@
/*-----------------------------------------*\
| FanController_NZXTKraken.cpp |
| |
| Generic Fan Interface for NZXT Kraken |
| |
| swilde 5/2021 |
\*-----------------------------------------*/
#include "FanController_NZXTKraken.h"
FanController_NZXTKraken::FanController_NZXTKraken(NZXTKrakenController* kraken_ptr)
{
kraken = kraken_ptr;
name = "NZXT Kraken X2";
description = "NZXT Kraken X42/X52/X62/X72";
version = kraken->GetFirmwareVersion();
location = kraken->GetLocation();
serial = kraken->GetSerialString();
kraken->UpdateStatus();
fan new_fan;
/*---------------------------------------------------------*\
| Add fan |
| X52 has a max fan RPM of 200, the X42 and X62 max is 1800 |
\*---------------------------------------------------------*/
new_fan.name = "NZXT Kraken Fan";
new_fan.speed_min = 25;
new_fan.speed_max = 100;
new_fan.speed_cmd = 100 * kraken->fan_speed / 2000;
new_fan.prev_speed_cmd = 0;
new_fan.rpm_rdg = kraken->fan_speed;
fans.push_back(new_fan);
/*---------------------------------------------------------*\
| Add pump |
\*---------------------------------------------------------*/
new_fan.name = "NZXT Kraken Pump";
new_fan.speed_min = 50;
new_fan.speed_max = 100;
new_fan.speed_cmd = 100 * kraken->pump_speed / 2800;
new_fan.prev_speed_cmd = 0;
new_fan.rpm_rdg = kraken->pump_speed;
fans.push_back(new_fan);
UpdateControl();
}
void FanController_NZXTKraken::UpdateControl()
{
if(fans[0].speed_cmd != fans[0].prev_speed_cmd)
{
kraken->SetSpeed(NZXT_KRAKEN_CHANNEL_FAN, fans[0].speed_cmd);
fans[0].prev_speed_cmd = fans[0].speed_cmd;
}
if(fans[1].speed_cmd != fans[1].prev_speed_cmd)
{
kraken->SetSpeed(NZXT_KRAKEN_CHANNEL_PUMP, fans[1].speed_cmd);
fans[1].prev_speed_cmd = fans[1].speed_cmd;
}
}
void FanController_NZXTKraken::UpdateReading()
{
kraken->UpdateStatus();
fans[0].rpm_rdg = kraken->fan_speed;
fans[1].rpm_rdg = kraken->pump_speed;
}
@@ -0,0 +1,23 @@
/*-----------------------------------------*\
| FanController_NZXTKraken.h |
| |
| Generic Fan Interface for NZXT Kraken |
| |
| swilde 5/2021 |
\*-----------------------------------------*/
#pragma once
#include "FanController.h"
#include "NZXTKrakenController.h"
class FanController_NZXTKraken : public FanController
{
public:
FanController_NZXTKraken(NZXTKrakenController* kraken_ptr);
void UpdateControl();
void UpdateReading();
private:
NZXTKrakenController* kraken;
};
@@ -41,6 +41,9 @@ NZXTKrakenController::NZXTKrakenController(hid_device* dev_handle, const char* p
| Get the firmware version |
\*-----------------------------------------------------*/
UpdateStatus();
int major_firmware_version = std::stoi(firmware_version.substr(0, firmware_version.find(".")));
supports_cooling_profiles = major_firmware_version >= 3;
}
NZXTKrakenController::~NZXTKrakenController()
@@ -196,3 +199,135 @@ void NZXTKrakenController::SendEffect
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 64);
}
void NZXTKrakenController::SetSpeed(unsigned char channel, unsigned int speed_cmd)
{
unsigned char duty;
/*-----------------------------------------------------*\
| Verify channel |
\*-----------------------------------------------------*/
if(channel == NZXT_KRAKEN_CHANNEL_FAN)
{
duty = std::max((unsigned char) 25, std::min((unsigned char) 100, (unsigned char) speed_cmd));
}
else if(channel == NZXT_KRAKEN_CHANNEL_PUMP)
{
duty = std::max((unsigned char) 50, std::min((unsigned char) 100, (unsigned char) speed_cmd));
}
else
{
return;
}
/*-----------------------------------------------------*\
| Write speed |
\*-----------------------------------------------------*/
if(supports_cooling_profiles)
{
SetFixedSpeedProfile(channel, duty);
}
else
{
SetInstantaneousSpeed(channel, duty);
}
}
void NZXTKrakenController::SetFixedSpeedProfile(unsigned char channel, unsigned char duty)
{
unsigned char usb_buf[64];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set to fan write |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x02;
usb_buf[0x01] = 0x4d;
usb_buf[0x02] = channel;
/*-----------------------------------------------------*\
| Generate steps |
\*-----------------------------------------------------*/
unsigned char temps[36];
for(int i = 0; i < 30; i++)
{
temps[i] = 20 + i;
}
for(int i = 0; i <= 5; i++)
{
temps[30 + i] = 50 + 2*i;
}
/*-----------------------------------------------------*\
| Write temp speed pairs |
\*-----------------------------------------------------*/
unsigned char curr_duty = duty;
for(int i = 0; i < 36; i++)
{
if(temps[i] == 60)
{
curr_duty = 100;
}
/*-----------------------------------------------------*\
| Set channel and index |
\*-----------------------------------------------------*/
usb_buf[0x02] = channel + i;
/*-----------------------------------------------------*\
| Set temp |
\*-----------------------------------------------------*/
usb_buf[0x03] = temps[i];
/*-----------------------------------------------------*\
| Set duty |
\*-----------------------------------------------------*/
usb_buf[0x04] = curr_duty;
/*-----------------------------------------------------*\
| Write speed |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 64);
}
}
void NZXTKrakenController::SetInstantaneousSpeed(unsigned char channel, unsigned char duty)
{
unsigned char usb_buf[64];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set to fan write |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x02;
usb_buf[0x01] = 0x4d;
/*-----------------------------------------------------*\
| Set channel |
\*-----------------------------------------------------*/
usb_buf[0x02] = channel;
/*-----------------------------------------------------*\
| Set temp (0 for instantaneous speed) |
\*-----------------------------------------------------*/
usb_buf[0x03] = 0;
/*-----------------------------------------------------*\
| Set duty |
\*-----------------------------------------------------*/
usb_buf[0x04] = duty;
/*-----------------------------------------------------*\
| Write speed |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 64);
}
@@ -48,6 +48,12 @@ enum
NZXT_KRAKEN_SPEED_FASTEST = 0x04, /* Fastest speed */
};
enum
{
NZXT_KRAKEN_CHANNEL_FAN = 0x80, /* Fan channel */
NZXT_KRAKEN_CHANNEL_PUMP = 0xc0, /* Pump channel */
};
class NZXTKrakenController
{
public:
@@ -58,6 +64,12 @@ public:
std::string GetLocation();
std::string GetSerialString();
void SetSpeed
(
unsigned char channel,
unsigned int speed_cmd
);
void UpdateEffect
(
NZXTKrakenChannel_t channel,
@@ -68,9 +80,12 @@ public:
std::vector<RGBColor> colors
);
private:
void UpdateStatus();
unsigned int fan_speed;
unsigned int pump_speed;
private:
void SendEffect
(
unsigned char channel,
@@ -83,12 +98,23 @@ private:
int size = 0
);
void SetFixedSpeedProfile
(
unsigned char channel,
unsigned char duty
);
void SetInstantaneousSpeed
(
unsigned char channel,
unsigned char duty
);
hid_device* dev;
// -- status
std::string firmware_version;
double liquid_temperature;
std::string location;
unsigned int fan_speed;
unsigned int pump_speed;
bool supports_cooling_profiles;
};
@@ -13,6 +13,7 @@
#include <hidapi.h>
#include "Detector.h"
#include "NZXTKrakenController.h"
#include "FanController_NZXTKraken.h"
#include "RGBController.h"
#include "RGBController_NZXTKraken.h"
@@ -37,6 +38,17 @@ void DetectNZXTKrakenControllers(hid_device_info* info, const std::string& name)
RGBController_NZXTKraken* rgb_controller = new RGBController_NZXTKraken(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
if(info->product_id == NZXT_KRAKEN_X2_PID)
{
/*---------------------------------------------*\
| Kraken M22 doesn't have liquid temp sensor or |
| ability to report or set fan or pump speeds |
\*---------------------------------------------*/
FanController_NZXTKraken* fan_controller = new FanController_NZXTKraken(controller);
fan_controller->name = name;
ResourceManager::get()->RegisterFanController(fan_controller);
}
}
} /* DetectNZXTKrakenControllers() */
@@ -0,0 +1,39 @@
/*-----------------------------------------*\
| FanController_Razer.cpp |
| |
| Generic Fan Interface for Razer Blade |
| laptops that support fan control |
| |
| Adam Honse (CalcProgrammer1) 6/23/2021 |
\*-----------------------------------------*/
#include "FanController_Razer.h"
FanController_Razer::FanController_Razer(RazerController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetName();
description = "Razer Device";
version = controller->GetFirmwareString();
fan new_fan;
new_fan.name = "Razer Blade Laptop Fan";
new_fan.speed_min = 0;
new_fan.speed_max = 5400;
new_fan.speed_cmd = 0;
new_fan.rpm_rdg = 0;
fans.push_back(new_fan);
}
void FanController_Razer::UpdateControl()
{
controller->SetFanRPM(fans[0].speed_cmd);
}
void FanController_Razer::UpdateReading()
{
}
@@ -0,0 +1,24 @@
/*-----------------------------------------*\
| FanController_Razer.h |
| |
| Generic Fan Interface for Razer Blade |
| laptops that support fan control |
| |
| Adam Honse (CalcProgrammer1) 6/23/2021 |
\*-----------------------------------------*/
#pragma once
#include "FanController.h"
#include "RazerController.h"
class FanController_Razer : public FanController
{
public:
FanController_Razer(RazerController* controller_ptr);
void UpdateControl();
void UpdateReading();
private:
RazerController* controller;
};
@@ -355,6 +355,18 @@ bool RazerController::SupportsBreathing()
return(supports_breathing);
}
void RazerController::SetFanRPM(unsigned int fan_rpm_cmd)
{
if(fan_rpm_cmd == 0)
{
razer_set_fan_rpm_cmd(true, 0);
}
else
{
razer_set_fan_rpm_cmd(false, fan_rpm_cmd);
}
}
bool RazerController::SupportsReactive()
{
return(false);
@@ -1796,6 +1808,29 @@ void RazerController::razer_set_mode_wave(unsigned char direction)
}
}
void RazerController::razer_set_fan_rpm_cmd(bool auto_fan_rpm, unsigned int fan_rpm_cmd)
{
struct razer_report mode_report = razer_create_report(0x0D, 0x02, 0x04);
mode_report.arguments[0] = 0x00;
mode_report.arguments[1] = 0x01;
mode_report.arguments[2] = 0x00;
mode_report.arguments[3] = auto_fan_rpm ? 0x00 : 0x01;
razer_usb_send(&mode_report);
if(!auto_fan_rpm)
{
struct razer_report fan_rpm_report = razer_create_report(0x0D, 0x01, 0x03);
fan_rpm_report.arguments[0] = 0x00;
fan_rpm_report.arguments[1] = 0x01;
fan_rpm_report.arguments[2] = (fan_rpm_cmd / 100);
razer_usb_send(&fan_rpm_report);
}
}
/*---------------------------------------------------------------------------------*\
| USB transfer functions |
\*---------------------------------------------------------------------------------*/
@@ -246,6 +246,8 @@ public:
void SetModeWave(unsigned char direction);
bool SupportsBreathing();
void SetFanRPM(unsigned int fan_rpm_cmd);
bool SupportsReactive();
bool SupportsWave();
@@ -341,6 +343,8 @@ private:
void razer_set_mode_static(unsigned char red, unsigned char grn, unsigned char blu);
void razer_set_mode_wave(unsigned char direction);
void razer_set_fan_rpm_cmd(bool auto_fan_rpm, unsigned int fan_rpm_cmd);
int razer_usb_receive(razer_report* report);
int razer_usb_send(razer_report* report);
int razer_usb_send_argb(razer_argb_report* report);
@@ -17,6 +17,8 @@
#include "RazerKrakenController.h"
#include "RazerDevices.h"
#include "ResourceManager.h"
#include "FanController.h"
#include "FanController_Razer.h"
#include "RGBController.h"
#include "RGBController_Razer.h"
#include "RGBController_RazerAddressable.h"
@@ -40,6 +42,12 @@ void DetectRazerControllers(hid_device_info* info, const std::string& name)
RGBController_Razer* rgb_controller = new RGBController_Razer(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
if(info->product_id == RAZER_BLADE_14_2021_PID)
{
FanController_Razer* fan_controller = new FanController_Razer(controller);
ResourceManager::get()->RegisterFanController(fan_controller);
}
}
} /* DetectRazerControllers() */
@@ -0,0 +1,61 @@
/*-----------------------------------------*\
| FanController_ThermaltakeRiing.cpp |
| |
| Generic Fan Interface for Thermaltake |
| Riing controller |
| |
| Adam Honse (CalcProgrammer1) 6/5/2020 |
\*-----------------------------------------*/
#include "FanController_ThermaltakeRiing.h"
FanController_ThermaltakeRiing::FanController_ThermaltakeRiing(ThermaltakeRiingController* riing_ptr)
{
riing = riing_ptr;
name = "Thermaltake Riing";
description = "Thermaltake Riing Device";
version = riing->GetFirmwareVersion();
for(std::size_t fan_index = 0; fan_index < THERMALTAKE_NUM_CHANNELS; fan_index++)
{
fan new_fan;
unsigned char speed;
unsigned short rpm;
riing->GetFanData(fan_index + 1, &speed, &rpm);
new_fan.name = "Thermaltake Riing Fan ";
new_fan.name.append(std::to_string(fan_index + 1));
new_fan.speed_min = THERMALTAKE_FAN_SPEED_MIN;
new_fan.speed_max = THERMALTAKE_FAN_SPEED_MAX;
new_fan.speed_cmd = speed;
new_fan.rpm_rdg = rpm;
fans.push_back(new_fan);
}
UpdateControl();
}
void FanController_ThermaltakeRiing::UpdateControl()
{
for(std::size_t fan_index = 0; fan_index < fans.size(); fan_index++)
{
riing->SendFan(fan_index + 1, THERMALTAKE_FAN_MODE_FIXED, fans[fan_index].speed_cmd);
}
}
void FanController_ThermaltakeRiing::UpdateReading()
{
for(std::size_t fan_index = 0; fan_index < fans.size(); fan_index++)
{
unsigned char speed;
unsigned short rpm;
riing->GetFanData(fan_index + 1, &speed, &rpm);
fans[fan_index].rpm_rdg = rpm;
}
}
@@ -0,0 +1,24 @@
/*-----------------------------------------*\
| FanController_ThermaltakeRiing.h |
| |
| Generic Fan Interface for Thermaltake |
| Riing controller |
| |
| Adam Honse (CalcProgrammer1) 6/5/2020 |
\*-----------------------------------------*/
#pragma once
#include "FanController.h"
#include "ThermaltakeRiingController.h"
class FanController_ThermaltakeRiing : public FanController
{
public:
FanController_ThermaltakeRiing(ThermaltakeRiingController* riing_ptr);
void UpdateControl();
void UpdateReading();
private:
ThermaltakeRiingController* riing;
};
@@ -44,9 +44,41 @@ std::string ThermaltakeRiingController::GetSerialString()
return(StringUtils::wstring_to_string(serial_string));
}
void ThermaltakeRiingController::GetFanData
(
unsigned char port,
unsigned char * speed,
unsigned short * rpm
)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up Get Fan Data packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x33;
usb_buf[0x02] = 0x51;
usb_buf[0x03] = port;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
hid_read(dev, usb_buf, 65);
*speed = usb_buf[0x04];
*rpm = (usb_buf[0x06] << 8) + usb_buf[0x05];
}
std::string ThermaltakeRiingController::GetFirmwareVersion()
{
unsigned char usb_buf[64];
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
@@ -56,14 +88,15 @@ std::string ThermaltakeRiingController::GetFirmwareVersion()
/*-----------------------------------------------------*\
| Set up Get Firmware Version packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x33;
usb_buf[0x01] = 0x50;
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x33;
usb_buf[0x02] = 0x50;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 64);
hid_read(dev, usb_buf, 64);
hid_write(dev, usb_buf, 65);
hid_read(dev, usb_buf, 65);
std::string ret_str = std::to_string(usb_buf[2]) + "." + std::to_string(usb_buf[3]) + "." + std::to_string(usb_buf[4]);
@@ -120,6 +153,37 @@ void ThermaltakeRiingController::SendInit()
hid_read(dev, usb_buf, 65);
}
void ThermaltakeRiingController::SendFan
(
unsigned char port,
unsigned char mode,
unsigned char speed
)
{
unsigned char usb_buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(usb_buf, 0x00, sizeof(usb_buf));
/*-----------------------------------------------------*\
| Set up RGB packet |
\*-----------------------------------------------------*/
usb_buf[0x00] = 0x00;
usb_buf[0x01] = 0x32;
usb_buf[0x02] = 0x51;
usb_buf[0x03] = port;
usb_buf[0x04] = mode;
usb_buf[0x05] = speed;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, usb_buf, 65);
hid_read(dev, usb_buf, 65);
}
void ThermaltakeRiingController::SendRGB
(
unsigned char port,
@@ -44,6 +44,18 @@ enum
THERMALTAKE_SPEED_EXTREME = 0x00
};
enum
{
THERMALTAKE_FAN_MODE_FIXED = 0x01,
THERMALTAKE_FAN_MODE_PWM = 0x02
};
enum
{
THERMALTAKE_FAN_SPEED_MIN = 20,
THERMALTAKE_FAN_SPEED_MAX = 100
};
#define THERMALTAKE_NUM_CHANNELS 5
class ThermaltakeRiingController
@@ -56,9 +68,23 @@ public:
std::string GetSerialString();
std::string GetFirmwareVersion();
void GetFanData
(
unsigned char port,
unsigned char * speed,
unsigned short * rpm
);
void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors);
void SetMode(unsigned char mode, unsigned char speed);
void SendFan
(
unsigned char port,
unsigned char mode,
unsigned char speed
);
private:
hid_device* dev;
@@ -68,15 +94,14 @@ private:
void SendInit();
void SendRGB
(
unsigned char port,
unsigned char mode,
unsigned char speed,
unsigned char num_colors,
unsigned char* color_data
);
void SendRGB
(
unsigned char port,
unsigned char mode,
unsigned char speed,
unsigned char num_colors,
unsigned char* color_data
);
void SendFan();
void SendSave();
};
@@ -15,6 +15,8 @@
#include "Detector.h"
#include "ThermaltakeRiingController.h"
#include "ThermaltakeRiingQuadController.h"
#include "FanController.h"
#include "FanController_ThermaltakeRiing.h"
#include "RGBController.h"
#include "RGBController_ThermaltakeRiing.h"
#include "RGBController_ThermaltakeRiingQuad.h"
@@ -40,6 +42,10 @@ void DetectThermaltakeRiingControllers(hid_device_info* info, const std::string&
RGBController_ThermaltakeRiing* rgb_controller = new RGBController_ThermaltakeRiing(controller);
// Constructor sets the name
ResourceManager::get()->RegisterRGBController(rgb_controller);
FanController_ThermaltakeRiing* fan_controller = new FanController_ThermaltakeRiing(controller);
ResourceManager::get()->RegisterFanController(fan_controller);
}
} /* DetectThermaltakeRiingControllers() */
+52
View File
@@ -0,0 +1,52 @@
/*-----------------------------------------*\
| FanController.h |
| |
| Definitions and types for generic fan |
| and pump controller interface |
| |
| Adam Honse (CalcProgrammer1) 6/5/2020 |
\*-----------------------------------------*/
#pragma once
#include <vector>
#include <string>
/*------------------------------------------------------------------*\
| Fan Type |
\*------------------------------------------------------------------*/
typedef struct
{
/*--------------------------------------------------------------*\
| Fan Information |
\*--------------------------------------------------------------*/
std::string name; /* Fan name */
unsigned int speed_cmd; /* Speed command */
unsigned int prev_speed_cmd; /* Last speed command */
unsigned int speed_min; /* Minimum speed command */
unsigned int speed_max; /* Maximum speed command */
unsigned int rpm_rdg; /* RPM reading */
} fan;
class FanController
{
public:
std::string name; /* controller name */
std::string description; /* controller description */
std::string version; /* controller version */
std::string serial; /* controller serial number */
std::string location; /* controller location */
std::vector<fan> fans; /* Fans */
/*---------------------------------------------------------*\
| FanController base class constructor |
\*---------------------------------------------------------*/
//FanController();
//~FanController();
/*---------------------------------------------------------*\
| Functions to be implemented in device implementation |
\*---------------------------------------------------------*/
virtual void UpdateControl() = 0;
virtual void UpdateReading() = 0;
};
+2
View File
@@ -122,6 +122,7 @@ INCLUDEPATH +=
super_io/ \
AutoStart/ \
KeyboardLayoutManager/ \
FanController/ \
RGBController/ \
qt/
@@ -159,6 +160,7 @@ HEADERS +=
super_io/super_io.h \
AutoStart/AutoStart.h \
KeyboardLayoutManager/KeyboardLayoutManager.h \
FanController/FanController.h \
RGBController/RGBController.h \
RGBController/RGBController_Dummy.h \
RGBController/RGBControllerKeyNames.h \
+1 -1
View File
@@ -166,4 +166,4 @@ While no code from these projects directly made its way into OpenRGB, these proj
* k550-macos https://github.com/vookimedlo/ck550-macos/tree/master
* luxafor-python https://github.com/vmitchell85/luxafor-python
* dreamcheekyusb https://github.com/gbrayut/dreamcheekyusb
* razer-laptop-control: https://github.com/rnd-ash/razer-laptop-control
+10
View File
@@ -191,6 +191,11 @@ std::vector<i2c_smbus_interface*> & ResourceManager::GetI2CBusses()
return busses;
}
void ResourceManager::RegisterFanController(FanController *fan_controller)
{
fan_controllers.push_back(fan_controller);
}
void ResourceManager::RegisterRGBController(RGBController *rgb_controller)
{
LOG_INFO("[%s] Registering RGB controller", rgb_controller->name.c_str());
@@ -254,6 +259,11 @@ void ResourceManager::UnregisterRGBController(RGBController* rgb_controller)
UpdateDeviceList();
}
std::vector<FanController*> & ResourceManager::GetFanControllers()
{
return fan_controllers;
}
std::vector<RGBController*> & ResourceManager::GetRGBControllers()
{
return rgb_controllers;
+8
View File
@@ -29,6 +29,7 @@
#define CONTROLLER_LIST_HID 0
struct hid_device_info;
class FanController;
class NetworkClient;
class NetworkServer;
class ProfileManager;
@@ -136,9 +137,11 @@ public:
void RegisterI2CBus(i2c_smbus_interface *);
std::vector<i2c_smbus_interface*> & GetI2CBusses();
void RegisterFanController(FanController *fan_controller);
void RegisterRGBController(RGBController *rgb_controller);
void UnregisterRGBController(RGBController *rgb_controller);
std::vector<FanController*> & GetFanControllers();
std::vector<RGBController*> & GetRGBControllers();
void RegisterI2CBusDetector (I2CBusDetectorFunction detector);
@@ -264,6 +267,11 @@ private:
\*-------------------------------------------------------------------------------------*/
std::vector<i2c_smbus_interface*> busses;
/*-------------------------------------------------------------------------------------*\
| FanControllers |
\*-------------------------------------------------------------------------------------*/
std::vector<FanController*> fan_controllers;
/*-------------------------------------------------------------------------------------*\
| RGBControllers |
\*-------------------------------------------------------------------------------------*/
+47
View File
@@ -13,6 +13,7 @@
#include "PluginManager.h"
#include "OpenRGBDevicePage.h"
#include "OpenRGBDeviceInfoPage.h"
#include "OpenRGBFanPage.h"
#include "OpenRGBServerInfoPage.h"
#include "OpenRGBConsolePage.h"
#include "OpenRGBPluginContainer.h"
@@ -1163,10 +1164,17 @@ void OpenRGBDialog2::ClearDevicesList()
ui->InformationTabBar->removeTab(tab_idx);
}
}
for(int tab_idx = 0; tab_idx < ui->FanTabBar->count(); tab_idx++)
{
delete ui->FanTabBar->widget(tab_idx);
}
ui->FanTabBar->clear();
}
void OpenRGBDialog2::UpdateDevicesList()
{
std::vector<FanController *> fan_controllers = ResourceManager::get()->GetFanControllers();
std::vector<RGBController *> controllers = ResourceManager::get()->GetRGBControllers();
/*-----------------------------------------------------*\
@@ -1332,6 +1340,45 @@ void OpenRGBDialog2::UpdateDevicesList()
base_tab += 1;
}
}
/*-----------------------------------------------------*\
| Remove all remaining device tabs |
\*-----------------------------------------------------*/
tab_count = ui->FanTabBar->count();
for(unsigned int tab_idx = 0; tab_idx < tab_count; tab_idx++)
{
unsigned int remove_idx = ui->FanTabBar->count() - 1;
QWidget* tab_widget = ui->FanTabBar->widget(remove_idx);
ui->FanTabBar->removeTab(remove_idx);
delete tab_widget;
}
/*-----------------------------------------------------*\
| Set up list of fan devices |
\*-----------------------------------------------------*/
QTabBar *FanTabBar = ui->FanTabBar->tabBar();
for(std::size_t fan_idx = 0; fan_idx < fan_controllers.size(); fan_idx++)
{
OpenRGBFanPage *NewPage = new OpenRGBFanPage(fan_controllers[fan_idx]);
ui->FanTabBar->addTab(NewPage, "");
/*-----------------------------------------------------*\
| Use Qt's HTML capabilities to display both icon and |
| text in the tab label. Choose icon based on device |
| type and append device name string. |
\*-----------------------------------------------------*/
QString NewLabelString = QString::fromStdString(fan_controllers[fan_idx]->name);
QLabel *NewTabLabel = new QLabel();
NewTabLabel->setText(NewLabelString);
NewTabLabel->setIndent(20);
NewTabLabel->setGeometry(0, 0, 200, 20);
FanTabBar->setTabButton(fan_idx, QTabBar::LeftSide, NewTabLabel);
}
}
void OpenRGBDialog2::SetDialogMessage(PLogMessage msg)
+1
View File
@@ -39,6 +39,7 @@
#include "PluginManager.h"
#include "i2c_smbus.h"
#include "FanController.h"
#include "LogManager.h"
#include "RGBController.h"
#include "ProfileManager.h"
+17
View File
@@ -60,6 +60,23 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="TabFans">
<attribute name="title">
<string>Fans</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QTabWidget" name="FanTabBar">
<property name="tabPosition">
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="TabSettings">
<attribute name="title">
<string>Settings</string>
+119
View File
@@ -0,0 +1,119 @@
#include <QTimer>
#include "OpenRGBFanPage.h"
using namespace Ui;
#ifdef _WIN32
#include <Windows.h>
#endif
#ifdef __APPLE__
#include <unistd.h>
static void Sleep(unsigned int milliseconds)
{
usleep(1000 * milliseconds);
}
#endif
#ifdef __linux__
#include <unistd.h>
static void Sleep(unsigned int milliseconds)
{
usleep(1000 * milliseconds);
}
#endif
OpenRGBFanPage::OpenRGBFanPage(FanController *dev, QWidget *parent) :
QFrame(parent),
ui(new Ui::OpenRGBFanPageUi)
{
ui->setupUi(this);
/*-----------------------------------------------------*\
| Store device pointer |
\*-----------------------------------------------------*/
device = dev;
fan_thread_running = true;
FanUpdateThread = new std::thread(&OpenRGBFanPage::FanUpdateThreadFunction, this);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, QOverload<>::of(&OpenRGBFanPage::UpdateRPM));
timer->start(1000);
/*-----------------------------------------------------*\
| Fill in the fan box |
\*-----------------------------------------------------*/
for (std::size_t i = 0; i < device->fans.size(); i++)
{
ui->FanBox->addItem(device->fans[i].name.c_str());
ui->SpeedSlider->setMinimum(device->fans[i].speed_min);
ui->SpeedSlider->setMaximum(device->fans[i].speed_max);
ui->SpeedSlider->setValue(device->fans[i].speed_cmd);
ui->RPMValue->setText(QString::number(device->fans[i].rpm_rdg));
}
/*-----------------------------------------------------*\
| Set to current values |
\*-----------------------------------------------------*/
on_FanBox_currentIndexChanged(0);
}
OpenRGBFanPage::~OpenRGBFanPage()
{
fan_thread_running = false;
FanUpdateThread->join();
delete ui;
}
void OpenRGBFanPage::FanUpdateThreadFunction()
{
while(fan_thread_running)
{
device->UpdateControl();
device->UpdateReading();
Sleep(1000);
}
}
void OpenRGBFanPage::UpdateRPM()
{
/*-----------------------------------------------------*\
| Read selected fan |
\*-----------------------------------------------------*/
unsigned int selected_fan = (unsigned int)ui->FanBox->currentIndex();
ui->RPMValue->setText(QString::number(device->fans[selected_fan].rpm_rdg));
}
void OpenRGBFanPage::on_FanBox_currentIndexChanged(int /*index*/)
{
/*-----------------------------------------------------*\
| Read selected fan |
\*-----------------------------------------------------*/
unsigned int selected_fan = (unsigned int)ui->FanBox->currentIndex();
ui->SpeedSlider->setMinimum(device->fans[selected_fan].speed_min);
ui->SpeedSlider->setMaximum(device->fans[selected_fan].speed_max);
ui->SpeedSlider->setValue(device->fans[selected_fan].speed_cmd);
UpdateRPM();
}
void OpenRGBFanPage::on_ModeBox_currentIndexChanged(int /*index*/)
{
}
void OpenRGBFanPage::on_SpeedSlider_valueChanged(int /* value */)
{
/*-----------------------------------------------------*\
| Read selected fan |
\*-----------------------------------------------------*/
unsigned int selected_fan = (unsigned int)ui->FanBox->currentIndex();
unsigned int speed_cmd = ui->SpeedSlider->value();
device->fans[selected_fan].speed_cmd = speed_cmd;
}
+45
View File
@@ -0,0 +1,45 @@
#ifndef OPENRGBFANPAGE_H
#define OPENRGBFANPAGE_H
#include "ui_OpenRGBFanPage.h"
#include "FanController.h"
#include <QFrame>
#include <thread>
namespace Ui {
class OpenRGBFanPage;
}
class Ui::OpenRGBFanPage : public QFrame
{
Q_OBJECT
public:
explicit OpenRGBFanPage(FanController *dev, QWidget *parent = nullptr);
~OpenRGBFanPage();
void FanUpdateThreadFunction();
void SetDevice(unsigned char red, unsigned char green, unsigned char blue);
void SetCustomMode();
void UpdateDevice();
void UpdateMode();
void UpdateModeUi();
private slots:
void UpdateRPM();
void on_FanBox_currentIndexChanged(int index);
void on_ModeBox_currentIndexChanged(int index);
void on_SpeedSlider_valueChanged(int value);
private:
Ui::OpenRGBFanPageUi *ui;
FanController *device;
bool fan_thread_running;
std::thread* FanUpdateThread;
signals:
};
#endif // OPENRGBDEVICEPAGE_H
+75
View File
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OpenRGBFanPageUi</class>
<widget class="QFrame" name="OpenRGBFanPageUi">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>683</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Frame</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1" colspan="3">
<widget class="QSlider" name="SpeedSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="FanBox"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="FanLabel">
<property name="text">
<string>Fan:</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="3">
<widget class="QComboBox" name="ModeBox"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="SpeedLabel">
<property name="text">
<string>Speed:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="RPMLabel">
<property name="text">
<string>RPM:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="ModeLabel">
<property name="text">
<string>Mode:</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QLabel" name="RPMValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>RPM Value</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>