Files
OpenRGB/Controllers/RazerController/RazerHanboController/RazerHanboController.cpp

263 lines
8.4 KiB
C++

/*---------------------------------------------------------*\
| RazerHanboController.cpp |
| |
| Driver for Razer Hanbo devices |
| |
| Joseph East (dripsnek) 12 Apr 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <string.h>
#include "RazerHanboController.h"
#include "RazerDevices.h"
using namespace std::chrono_literals;
RazerHanboController::RazerHanboController(hid_device* dev_handle, const char* path, unsigned short pid, std::string dev_name)
{
dev = dev_handle;
dev_pid = pid;
location = path;
name = dev_name;
device_index = 0;
for(unsigned int i = 0; i < RAZER_NUM_DEVICES; i++)
{
if(device_list[i]->pid == dev_pid)
{
device_index = i;
}
}
GetFirmware();
SetDirectMode();
}
RazerHanboController::~RazerHanboController()
{
hid_close(dev);
}
unsigned int RazerHanboController::GetDeviceIndex()
{
return(device_index);
}
device_type RazerHanboController::GetDeviceType()
{
return(device_list[device_index]->type);
}
std::string RazerHanboController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string RazerHanboController::GetFirmwareString()
{
return firmware_version;
}
std::string RazerHanboController::GetSerialString()
{
return serial_string;
}
std::string RazerHanboController::GetName()
{
return(name);
}
void RazerHanboController::SetDirectMode()
{
razer_hanbo_report request_report = razer_hanbo_create_report(0x82);
razer_hanbo_report response_report = razer_hanbo_create_report(0x00);
/*---------------------------------------*\
| Take the one request and transform as |
| appropriate for the sequence. |
\*---------------------------------------*/
request_report.arguments[0] = 0x01;
UsbSend(&request_report);
UsbReceive(&response_report);
request_report.header[1] = 0x80;
request_report.arguments[0] = 0x01;
request_report.arguments[1] = 0x00;
request_report.arguments[2] = 0x01;
UsbSend(&request_report);
UsbReceive(&response_report);
request_report.header[1] = 0x80;
request_report.arguments[0] = 0x01;
request_report.arguments[1] = 0x01;
request_report.arguments[2] = 0x01;
UsbSend(&request_report);
UsbReceive(&response_report);
memset(&request_report, 0, sizeof(razer_hanbo_report));
request_report.header[1] = 0x82;
request_report.arguments[0] = 0x01;
UsbSend(&request_report);
UsbReceive(&response_report);
}
void RazerHanboController::SetModeOff()
{
SetDirectMode();
}
void RazerHanboController::SetModeSpectrumCycle()
{
razer_hanbo_report request_report = razer_hanbo_create_report(0x82);
razer_hanbo_report response_report = razer_hanbo_create_report(0x00);
request_report.arguments[0] = 0x01;
UsbSend(&request_report);
UsbReceive(&response_report);
request_report.header[1] = 0x80;
request_report.arguments[0] = 0x01;
UsbSend(&request_report);
UsbReceive(&response_report);
request_report.header[1] = 0x80;
request_report.arguments[0] = 0x01;
request_report.arguments[1] = 0x01;
UsbSend(&request_report);
UsbReceive(&response_report);
}
void RazerHanboController::SetZoneLeds(int zone_idx, const zone& input_zone)
{
razer_hanbo_report request_report = razer_hanbo_create_report(0x32);
std::string payload;
unsigned int j = 0;
if(zone_idx > PUMP)
request_report.header[1] = 0x40;
payload = "0107000000000" + std::to_string(zone_idx);
for(unsigned int i = 0; i < payload.length(); i += 2)
{
std::string byteString = payload.substr(i, 2);
char byte = (char)strtol(byteString.c_str(), NULL, 16);
request_report.arguments[j] = byte;
j++;
}
/*--------------------------------------------*\
| The color command format is G/R/B |
\*--------------------------------------------*/
for(unsigned int i = 0; i < input_zone.leds_count; i++)
{
request_report.arguments[j] = RGBGetGValue(input_zone.colors[i]);
j++;
request_report.arguments[j] = RGBGetRValue(input_zone.colors[i]);
j++;
request_report.arguments[j] = RGBGetBValue(input_zone.colors[i]);
j++;
}
/*--------------------------------------------*\
| Writing RGB values does not generate ack |
| reports from the cooler. Add a gap between |
| transactions to not overwhelm it. |
\*--------------------------------------------*/
UsbSend(&request_report);
std::this_thread::sleep_for(2ms);
}
/*--------------------------------------------*\
| The Hanbo allows for individual brightness |
| of the pump cap and fans. OpenRGB only has |
| a single brightness slider. Whilst this |
| function can support individual settings, |
| most of the time they will be invoked with |
| identical values |
\*--------------------------------------------*/
void RazerHanboController::SetBrightness(int zone, unsigned int brightness)
{
razer_hanbo_report request_report = razer_hanbo_create_report(0x70);
razer_hanbo_report response_report = razer_hanbo_create_report(0x00);
request_report.arguments[0] = 0x01;
request_report.arguments[1] = 0x00;
if(zone > PUMP)
request_report.arguments[1] = 0x01;
request_report.arguments[2] = brightness & 0xFF;
UsbSend(&request_report);
UsbReceive(&response_report);
}
/*---------------------------------------------------------------------------------*\
| Basic report and response creation function |
\*---------------------------------------------------------------------------------*/
razer_hanbo_report RazerHanboController::razer_hanbo_create_report(unsigned char header)
{
/*---------------------------------------------------------*\
| One type supports both requests and responses. |
| Requests start at header[1] to provide a dummy byte. |
| Responses provide 0 to this function for consistency |
\*---------------------------------------------------------*/
razer_hanbo_report new_report;
memset(&new_report, 0, sizeof(razer_hanbo_report));
new_report.header[1] = header;
return new_report;
}
/*---------------------------------------------------------------------------------*\
| Get functions (request information from device) |
\*---------------------------------------------------------------------------------*/
void RazerHanboController::GetFirmware()
{
razer_hanbo_report request_report = razer_hanbo_create_report(0x01);
razer_hanbo_report response_report = razer_hanbo_create_report(0x00);
request_report.arguments[0] = 0x01;
UsbSend(&request_report);
/*---------------------------------------*\
| The Hanbo sends firmware reports twice |
\*---------------------------------------*/
UsbReceive(&response_report);
UsbReceive(&response_report);
if(response_report.header[0] == 0x02)
{
std::string ret_serial(response_report.arguments, response_report.arguments+15);
std::vector<unsigned char> firmware_ret(response_report.arguments+27, response_report.arguments+29);
char major = firmware_ret[0];
char minor = firmware_ret[1] >> 4 & 0x0F;
char patch = firmware_ret[1] & 0x0F;
char ver[12];
snprintf(ver, sizeof(ver), "%hhu.%hhu.%hhu", major, minor, patch);
serial_string = ret_serial;
firmware_version = std::string(ver);
}
}
/*---------------------------------------------------------------------------------*\
| USB transfer functions |
\*---------------------------------------------------------------------------------*/
int RazerHanboController::UsbReceive(razer_hanbo_report* report)
{
return hid_read_timeout(dev, (unsigned char*)report, sizeof(*report),2);
}
int RazerHanboController::UsbSend(razer_hanbo_report* report)
{
return hid_write(dev, (unsigned char*)report, sizeof(*report));
}