From 90508f7f1bfdee44756ecc2d307a0fe3ae7a6912 Mon Sep 17 00:00:00 2001 From: Joseph E Date: Wed, 23 Apr 2025 13:07:34 +0000 Subject: [PATCH] Initial Razer Hanbo Chroma support --- .../RazerController/RazerControllerDetect.cpp | 24 ++ Controllers/RazerController/RazerDevices.cpp | 73 +++++ Controllers/RazerController/RazerDevices.h | 1 + .../RGBController_RazerHanbo.cpp | 189 +++++++++++++ .../RGBController_RazerHanbo.h | 43 +++ .../RazerHanboController.cpp | 262 ++++++++++++++++++ .../RazerHanboController.h | 103 +++++++ 7 files changed, 695 insertions(+) create mode 100644 Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.cpp create mode 100644 Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.h create mode 100644 Controllers/RazerController/RazerHanboController/RazerHanboController.cpp create mode 100644 Controllers/RazerController/RazerHanboController/RazerHanboController.h diff --git a/Controllers/RazerController/RazerControllerDetect.cpp b/Controllers/RazerController/RazerControllerDetect.cpp index 548e7ec7..562ae3b8 100644 --- a/Controllers/RazerController/RazerControllerDetect.cpp +++ b/Controllers/RazerController/RazerControllerDetect.cpp @@ -14,11 +14,13 @@ #include "Detector.h" #include "RazerController.h" #include "RazerKrakenController.h" +#include "RazerHanboController.h" #include "RazerDevices.h" #include "ResourceManager.h" #include "RGBController_Razer.h" #include "RGBController_RazerAddressable.h" #include "RGBController_RazerKraken.h" +#include "RGBController_RazerHanbo.h" /******************************************************************************************\ * * @@ -151,6 +153,27 @@ void DetectRazerKrakenControllers(hid_device_info* info, const std::string& name } } /* DetectRazerKrakenControllers() */ +/******************************************************************************************\ +* * +* DetectRazerHanboController * +* * +* Tests the USB address to see if a Razer Hanbo controller exists there. * +* * +\******************************************************************************************/ + +void DetectRazerHanboControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + RazerHanboController* controller = new RazerHanboController(dev, info->path, info->product_id, name); + + RGBController_RazerHanbo* rgb_controller = new RGBController_RazerHanbo(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} /* DetectRazerHanboControllers() */ + /*-----------------------------------------------------------------------------------------------------*\ | Keyboards | \*-----------------------------------------------------------------------------------------------------*/ @@ -354,6 +377,7 @@ REGISTER_HID_DETECTOR_IPU("Razer Mouse Dock Pro", Det REGISTER_HID_DETECTOR_IPU("Lian Li O11 Dynamic - Razer Edition", DetectRazerControllers, RAZER_VID, RAZER_O11_DYNAMIC_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_PU("Razer Seiren Emote", DetectRazerControllers, RAZER_VID, RAZER_SEIREN_EMOTE_PID, 0x0C, 0x01 ); REGISTER_HID_DETECTOR_PU("Razer Thunderbolt 4 Dock Chroma", DetectRazerControllers, RAZER_VID, RAZER_THUNDERBOLT_4_DOCK_CHROMA_PID, 0x0C, 0x01 ); +REGISTER_HID_DETECTOR_IPU("Razer Hanbo Chroma", DetectRazerHanboControllers, RAZER_VID, RAZER_HANBO_CHROMA_PID, 0x00, 0xFF00, 0x01); /*-----------------------------------------------------------------------------------------------------*\ | Nommo devices seem to have an issue where interface 1 doesn't show on Linux or MacOS. Due to the way | diff --git a/Controllers/RazerController/RazerDevices.cpp b/Controllers/RazerController/RazerDevices.cpp index e7f9a1be..dbdbb7a7 100644 --- a/Controllers/RazerController/RazerDevices.cpp +++ b/Controllers/RazerController/RazerDevices.cpp @@ -8516,6 +8516,78 @@ static const razer_device thunderbolt_4_dock_chroma_device = NULL }; +/*-------------------------------------------------------------*\ +| Razer Hanbo Chroma | +| | +| Zone "Pump" | +| Linear | +| 16 LEDs | +| | +| Zone "Fan 1" | +| Linear | +| 18 LEDs | +| | +| Zone "Fan 2" | +| Linear | +| 18 LEDs | +| | +| Zone "Fan 3" | +| Linear | +| 18 LEDs | +| | +\*-------------------------------------------------------------*/ +static const razer_zone hanbo_chroma_pump_zone = +{ + "Pump", + ZONE_TYPE_LINEAR, + 1, + 16 +}; + +static const razer_zone hanbo_chroma_fan_one_zone = +{ + "Fan 1", + ZONE_TYPE_LINEAR, + 1, + 18 +}; + +static const razer_zone hanbo_chroma_fan_two_zone = +{ + "Fan 2", + ZONE_TYPE_LINEAR, + 1, + 18 +}; + +static const razer_zone hanbo_chroma_fan_three_zone = +{ + "Fan 3", + ZONE_TYPE_LINEAR, + 1, + 18 +}; + +static const razer_device hanbo_chroma_device = +{ + "Razer Hanbo Chroma", + RAZER_HANBO_CHROMA_PID, + DEVICE_TYPE_COOLER, + RAZER_MATRIX_TYPE_EXTENDED, + 0x3F, + 1, + 70, + { + &hanbo_chroma_pump_zone, + &hanbo_chroma_fan_one_zone, + &hanbo_chroma_fan_two_zone, + &hanbo_chroma_fan_three_zone, + NULL, + NULL + }, + NULL +}; + /*-------------------------------------------------------------------------*\ | DEVICE MASTER LIST | \*-------------------------------------------------------------------------*/ @@ -8719,6 +8791,7 @@ const razer_device* razer_device_list[] = &o11_dynamic_device, &seiren_emote_device, &thunderbolt_4_dock_chroma_device, + &hanbo_chroma_device }; const unsigned int RAZER_NUM_DEVICES = (sizeof(razer_device_list) / sizeof(razer_device_list[ 0 ])); diff --git a/Controllers/RazerController/RazerDevices.h b/Controllers/RazerController/RazerDevices.h index d170ab05..373a9267 100644 --- a/Controllers/RazerController/RazerDevices.h +++ b/Controllers/RazerController/RazerDevices.h @@ -258,6 +258,7 @@ #define RAZER_SEIREN_EMOTE_PID 0x0F1B #define RAZER_STRIDER_CHROMA_PID 0x0C05 #define RAZER_THUNDERBOLT_4_DOCK_CHROMA_PID 0x0F21 +#define RAZER_HANBO_CHROMA_PID 0x0F35 typedef struct { diff --git a/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.cpp b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.cpp new file mode 100644 index 00000000..4b11be80 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.cpp @@ -0,0 +1,189 @@ +/*---------------------------------------------------------*\ +| RGBController_RazerHanbo.cpp | +| | +| RGBController for Razer Hanbo devices | +| | +| Joseph East (dripsnek) 12 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RazerHanbo.h" +#include "RazerDevices.h" + +/**------------------------------------------------------------------*\ + @name Razer Hanbo Chroma + @category Cooler + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRazerHanboControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RazerHanbo::RGBController_RazerHanbo(RazerHanboController* controller_ptr) +{ + controller = controller_ptr; + name = controller->GetName(); + vendor = "Razer"; + type = controller->GetDeviceType(); + description = "Razer Hanbo Device"; + location = controller->GetDeviceLocation(); + version = controller->GetFirmwareString(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = RAZER_HANBO_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = MIN_BRIGHTNESS; + Direct.brightness_max = MAX_BRIGHTNESS; + Direct.brightness = MAX_BRIGHTNESS/2; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = RAZER_HANBO_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = RAZER_HANBO_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = 0; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + local_mode = RAZER_HANBO_MODE_DIRECT; + + SetupZones(); +} + +RGBController_RazerHanbo::~RGBController_RazerHanbo() +{ + delete controller; +} + +void RGBController_RazerHanbo::SetupZones() +{ + unsigned int device_index = controller->GetDeviceIndex(); + + /*---------------------------------------------------------*\ + | Fill in zone information based on device table | + \*---------------------------------------------------------*/ + for(unsigned int zone_id = 0; zone_id < RAZER_MAX_ZONES; zone_id++) + { + if(device_list[device_index]->zones[zone_id] != NULL) + { + zone new_zone; + + new_zone.name = device_list[device_index]->zones[zone_id]->name; + new_zone.type = device_list[device_index]->zones[zone_id]->type; + new_zone.leds_count = device_list[device_index]->zones[zone_id]->rows * device_list[device_index]->zones[zone_id]->cols; + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + + if(new_zone.type == ZONE_TYPE_MATRIX) + { + matrix_map_type * new_map = new matrix_map_type; + + new_zone.matrix_map = new_map; + new_map->height = device_list[device_index]->zones[zone_id]->rows; + new_map->width = device_list[device_index]->zones[zone_id]->cols; + new_map->map = new unsigned int[new_map->height * new_map->width]; + + 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] = (y * new_map->width) + x; + } + } + } + else + { + new_zone.matrix_map = NULL; + } + + zones.push_back(new_zone); + } + } + + for(unsigned int zone_id = 0; zone_id < zones.size(); zone_id++) + { + for(unsigned int row_id = 0; row_id < device_list[device_index]->zones[zone_id]->rows; row_id++) + { + for(unsigned int col_id = 0; col_id < device_list[device_index]->zones[zone_id]->cols; col_id++) + { + led* new_led = new led(); + + new_led->name = device_list[device_index]->zones[zone_id]->name; + + if(zones[zone_id].leds_count > 1) + { + new_led->name.append(" LED "); + new_led->name.append(std::to_string(col_id + 1)); + } + + leds.push_back(*new_led); + } + } + } + + SetupColors(); +} + +void RGBController_RazerHanbo::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RazerHanbo::DeviceUpdateLEDs() +{ + UpdateZoneLEDs(PUMP); + UpdateZoneLEDs(FAN1); + UpdateZoneLEDs(FAN2); + UpdateZoneLEDs(FAN3); +} + +/*---------------------------------------------------------*\ +| The Hanbo command set is arranged in terms of zones. | +| Transactions are straight forward when grouped this way. | +\*---------------------------------------------------------*/ + +void RGBController_RazerHanbo::UpdateZoneLEDs(int zoneid) +{ + controller->SetZoneLeds(zoneid, this->zones[zoneid]); +} + +void RGBController_RazerHanbo::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RazerHanbo::DeviceUpdateMode() +{ + switch(modes[active_mode].value) + { + case RAZER_HANBO_MODE_DIRECT: + if(local_mode != RAZER_HANBO_MODE_DIRECT) + controller->SetDirectMode(); + break; + + case RAZER_HANBO_MODE_OFF: + controller->SetModeOff(); + break; + + case RAZER_HANBO_MODE_SPECTRUM_CYCLE: + controller->SetModeSpectrumCycle(); + break; + } + + local_mode = modes[active_mode].value; +} diff --git a/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.h b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.h new file mode 100644 index 00000000..4ca14d54 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_Razer.h | +| | +| RGBController for Razer Hanbo devices | +| | +| Joseph East (dripsnek) 12 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RazerHanboController.h" + +enum +{ + RAZER_HANBO_MODE_DIRECT, + RAZER_HANBO_MODE_OFF, + RAZER_HANBO_MODE_SPECTRUM_CYCLE, +}; + +class RGBController_RazerHanbo : public RGBController +{ +public: + RGBController_RazerHanbo(RazerHanboController* controller_ptr); + ~RGBController_RazerHanbo(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RazerHanboController* controller; + int local_mode; +}; diff --git a/Controllers/RazerController/RazerHanboController/RazerHanboController.cpp b/Controllers/RazerController/RazerHanboController/RazerHanboController.cpp new file mode 100644 index 00000000..ee69e4e7 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RazerHanboController.cpp @@ -0,0 +1,262 @@ +/*---------------------------------------------------------*\ +| 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-only | +\*---------------------------------------------------------*/ + +#include +#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 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[6]; + + snprintf(ver, sizeof(ver), "%u.%u.%u", 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)); +} diff --git a/Controllers/RazerController/RazerHanboController/RazerHanboController.h b/Controllers/RazerController/RazerHanboController/RazerHanboController.h new file mode 100644 index 00000000..6f257db8 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RazerHanboController.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------*\ +| RazerHanboController.h | +| | +| 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-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +/*---------------------------------------------------------*\ +| Struct packing macro for GCC and MSVC | +\*---------------------------------------------------------*/ +#ifdef __GNUC__ +#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#endif + +#ifdef _MSC_VER +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +#endif + +/*---------------------------------------------------------*\ +| The Hanbo does not advertise HID report IDs. | +| In this case under Windows, payloads sent to hidapi must | +| be prefixed with a byte of value 0 even if this exceeds | +| the device report length. This dummy byte never ends up | +| on the wire. Hidapi via libusb under Linux is compatible | +| with this behavior. This is generally not compatible with | +| hidraw when using it directly. | +| | +| Request payloads start at header[1] to make this byte. | +| Responses are unaffected and start at header[0]. | +\*---------------------------------------------------------*/ +PACK(struct razer_hanbo_report +{ + unsigned char header[2]; + unsigned char arguments[63]; +}); + +enum +{ + MIN_BRIGHTNESS = 0x00, + MAX_BRIGHTNESS = 0x64, +}; + +enum +{ + PUMP, + FAN1, + FAN2, + FAN3 +}; + +class RazerHanboController +{ +public: + RazerHanboController(hid_device* dev_handle, const char* path, unsigned short pid, std::string dev_name); + ~RazerHanboController(); + + unsigned int GetDeviceIndex(); + device_type GetDeviceType(); + std::string GetDeviceLocation(); + std::string GetFirmwareString(); + std::string GetSerialString(); + std::string GetName(); + void SetDirectMode(); + void SetModeOff(); + void SetModeSpectrumCycle(); + void SetZoneLeds(int zone_idc, const zone& input_zone); + void SetBrightness(int zone, unsigned int brightness); + +private: + hid_device* dev; + unsigned short dev_pid; + + /*---------------------------------------------------------*\ + | Device information strings | + \*---------------------------------------------------------*/ + std::string firmware_version; + std::string serial_string; + std::string location; + std::string name; + + /*---------------------------------------------------------*\ + | Index of device in Razer device list | + \*---------------------------------------------------------*/ + unsigned int device_index; + + /*---------------------------------------------------------*\ + | Private functions | + \*---------------------------------------------------------*/ + razer_hanbo_report razer_hanbo_create_report(unsigned char header); + void GetFirmware(); + int UsbReceive(razer_hanbo_report* report); + int UsbSend(razer_hanbo_report* report); +};