Initial commit for HyperX Quadcast S
This commit is contained in:
parent
856fbc1bb2
commit
72fa099088
6 changed files with 682 additions and 0 deletions
|
|
@ -0,0 +1,210 @@
|
|||
/*-----------------------------------------*\
|
||||
| HyperXQuadcastSController.cpp |
|
||||
| |
|
||||
| Implementation for the HyperX |
|
||||
| Quadcast S RGB microphone |
|
||||
| |
|
||||
| Matt Silva (thesilvanator) 2022 |
|
||||
\*-----------------------------------------*/
|
||||
#include "HyperXQuadcastSController.h"
|
||||
|
||||
HyperXQuadcastSController::HyperXQuadcastSController(hid_device* dev_handle, HXQS_HIDAPI_WRAPPER wrapper, std::string path)
|
||||
{
|
||||
hidapi_wrapper = wrapper;
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
|
||||
wchar_t serial_string[128];
|
||||
int ret = wrapper.get_serial_num_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
serial_number = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wstring return_wstring = serial_string;
|
||||
serial_number = std::string(return_wstring.begin(), return_wstring.end());
|
||||
}
|
||||
}
|
||||
|
||||
HyperXQuadcastSController::~HyperXQuadcastSController()
|
||||
{
|
||||
|
||||
if(dev)
|
||||
{
|
||||
hidapi_wrapper.close(dev);
|
||||
}
|
||||
}
|
||||
|
||||
std::string HyperXQuadcastSController::GetDeviceLocation()
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
std::string HyperXQuadcastSController::GetSerialString()
|
||||
{
|
||||
return serial_number;
|
||||
}
|
||||
|
||||
|
||||
void HyperXQuadcastSController::SaveColors(std::vector<RGBColor> colors, unsigned int num_frames)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
int res;
|
||||
unsigned int num_color_packets = 0;
|
||||
unsigned int frame = 0;
|
||||
unsigned char color[HXQS_PACKET_SIZE] = {0};
|
||||
unsigned char empty[HXQS_PACKET_SIZE] = {0};
|
||||
|
||||
num_color_packets = num_frames/8;
|
||||
if(num_frames % 8)
|
||||
{
|
||||
num_color_packets++;
|
||||
}
|
||||
|
||||
lock.lock();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Start Save Transaction |
|
||||
| 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
||||
\*---------------------------------------------------------*/
|
||||
SendToRegister(0x53, (uint8_t)num_color_packets, 0);
|
||||
|
||||
while(frame < num_frames)
|
||||
{
|
||||
memset(color, 0, HXQS_PACKET_SIZE);
|
||||
|
||||
unsigned int i = 0;
|
||||
while(i < 8 && frame < num_frames)
|
||||
{
|
||||
int index = HXQS_FRAME_SIZE * i;
|
||||
RGBColor top = colors[frame*2];
|
||||
RGBColor bot = colors[frame*2 + 1];
|
||||
|
||||
color[index + 1] = 0x81;
|
||||
color[index + 2] = RGBGetRValue(top);
|
||||
color[index + 3] = RGBGetGValue(top);
|
||||
color[index + 4] = RGBGetBValue(top);
|
||||
color[index + 5] = 0x81;
|
||||
color[index + 6] = RGBGetRValue(bot);
|
||||
color[index + 7] = RGBGetGValue(bot);
|
||||
color[index + 8] = RGBGetBValue(bot);
|
||||
|
||||
i++;
|
||||
frame++;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(15ms);
|
||||
res = hidapi_wrapper.send_feature_report(dev,color,HXQS_PACKET_SIZE);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Post Save Transaction |
|
||||
| 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
||||
\*---------------------------------------------------------*/
|
||||
SendToRegister(0x02, 0, 0);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Stop Save Transaction |
|
||||
| 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
||||
\*---------------------------------------------------------*/
|
||||
SendToRegister(0x23, 1, 0);
|
||||
|
||||
SendEOT((uint8_t)num_frames);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Post Save Transaction |
|
||||
| 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
||||
\*---------------------------------------------------------*/
|
||||
SendToRegister(0x02, 0, 0);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// likes to have one temporary direct packet after the save for some reason
|
||||
SendDirect(colors);
|
||||
}
|
||||
|
||||
void HyperXQuadcastSController::SendDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
if(colors.size() != 2)
|
||||
{
|
||||
LOG_ERROR("[HyperX Quadcast S] Unable to send direct packet, incorrect size: %d", colors.size());
|
||||
return;
|
||||
}
|
||||
|
||||
int res;
|
||||
RGBColor c1 = colors[0];
|
||||
RGBColor c2 = colors[1];
|
||||
uint8_t buffer[HXQS_PACKET_SIZE];
|
||||
|
||||
// colour packet
|
||||
memset(buffer,0,HXQS_PACKET_SIZE);
|
||||
|
||||
//buffer[0x00] = 0; //buffer requires 0 at index 0 as device does not use ReportIDs
|
||||
buffer[0x01] = 0x81;
|
||||
buffer[0x02] = RGBGetRValue(c1);
|
||||
buffer[0x03] = RGBGetGValue(c1);
|
||||
buffer[0x04] = RGBGetBValue(c1);
|
||||
buffer[0x05] = 0x81;
|
||||
buffer[0x06] = RGBGetRValue(c2);
|
||||
buffer[0x07] = RGBGetGValue(c2);
|
||||
buffer[0x08] = RGBGetBValue(c2);
|
||||
|
||||
lock.lock();
|
||||
|
||||
res = hidapi_wrapper.send_feature_report(dev, buffer, HXQS_PACKET_SIZE);
|
||||
std::this_thread::sleep_for(15ms);
|
||||
|
||||
SendToRegister(0xF2, 0, 1);
|
||||
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
void HyperXQuadcastSController::SendEOT(uint8_t frame_count)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
uint8_t buffer[HXQS_PACKET_SIZE];
|
||||
|
||||
memset(buffer,0,HXQS_PACKET_SIZE);
|
||||
|
||||
//buffer[0x00] = 0; //buffer requires 0 at index 0 as device does not use ReportIDs
|
||||
buffer[0x01] = 0x08;
|
||||
buffer[0x3C] = 0x28;
|
||||
buffer[0x3D] = frame_count;
|
||||
buffer[0x3E] = 0x00;
|
||||
buffer[0x3F] = 0xAA;
|
||||
buffer[0x40] = 0x55;
|
||||
|
||||
int result = hidapi_wrapper.send_feature_report(dev,buffer,HXQS_PACKET_SIZE);
|
||||
LOG_DEBUG("[HyperX Quadcast S] SendEOT with frame count %02X wrote %d bytes", frame_count, result);
|
||||
std::this_thread::sleep_for(15ms);
|
||||
}
|
||||
|
||||
void HyperXQuadcastSController::SendToRegister(uint8_t reg, uint8_t param1, uint8_t param2)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
uint8_t buffer[HXQS_PACKET_SIZE];
|
||||
|
||||
memset(buffer,0,HXQS_PACKET_SIZE);
|
||||
|
||||
//buffer[0x00] = 0; //buffer requires 0 at index 0 as device does not use ReportIDs
|
||||
buffer[0x01] = 0x04;
|
||||
buffer[0x02] = reg; // 0xF2 Apply, 0x53 Save
|
||||
buffer[0x08] = param1;
|
||||
buffer[0x09] = param2;
|
||||
|
||||
int result = hidapi_wrapper.send_feature_report(dev, buffer, HXQS_PACKET_SIZE);
|
||||
if(result < 0)
|
||||
{
|
||||
LOG_ERROR("[HyperX Quadcast S] SendToRegister failed: %ls", hidapi_wrapper.error(dev));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("[HyperX Quadcast S] SendToRegister %02X with P1 %02X P2 %02X wrote %d bytes", reg, param1, param2, result);
|
||||
}
|
||||
std::this_thread::sleep_for(15ms);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*-----------------------------------------*\
|
||||
| HyperXQuadcastSController.h |
|
||||
| |
|
||||
| Implementation for the HyperX |
|
||||
| Quadcast S RGB microphone |
|
||||
| |
|
||||
| Matt Silva (thesilvanator) 2022 |
|
||||
\*-----------------------------------------*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi/hidapi.h>
|
||||
#include "LogManager.h"
|
||||
#include "RGBController.h"
|
||||
|
||||
#define HXQS_PACKET_SIZE 64 + 1
|
||||
#define HXQS_FRAME_SIZE 8
|
||||
|
||||
// wrapper typedefs
|
||||
typedef int (*HXQS_Report_Send_t)(hid_device*, const unsigned char*, size_t);
|
||||
typedef int (*HXQS_Report_Get_t)(hid_device*, unsigned char*, size_t);
|
||||
typedef int (*HXQS_Get_Serial_t)(hid_device*, wchar_t*, size_t);
|
||||
typedef hid_device* (*HXQS_hid_open_path_t)(const char*);
|
||||
typedef hid_device_info* (*HXQS_hid_enumerate_t) (unsigned short, unsigned short);
|
||||
typedef void (*HXQS_hid_free_enumeration_t)(hid_device_info*);
|
||||
typedef void (*HXQS_hid_close_t)(hid_device*);
|
||||
typedef const wchar_t* (*HXQS_hid_error_t) (hid_device*);
|
||||
|
||||
/*----------------------------------------------------*\
|
||||
| See comment at top of HyperXQuadcastSDetect.cpp for |
|
||||
| details about the hidapi wrapper for this device |
|
||||
\*----------------------------------------------------*/
|
||||
struct HXQS_HIDAPI_WRAPPER {
|
||||
void* dyn_handle;
|
||||
HXQS_Report_Send_t send_feature_report;
|
||||
HXQS_Report_Get_t get_feature_report;
|
||||
HXQS_Get_Serial_t get_serial_num_string;
|
||||
HXQS_hid_open_path_t open_path;
|
||||
HXQS_hid_enumerate_t enumerate;
|
||||
HXQS_hid_free_enumeration_t free_enumeration;
|
||||
HXQS_hid_close_t close;
|
||||
HXQS_hid_error_t error;
|
||||
};
|
||||
|
||||
class HyperXQuadcastSController
|
||||
{
|
||||
public:
|
||||
HyperXQuadcastSController(hid_device* dev, HXQS_HIDAPI_WRAPPER wrapper, std::string path);
|
||||
~HyperXQuadcastSController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SendDirect(std::vector<RGBColor> color_data);
|
||||
void SaveColors(std::vector<RGBColor> colors, unsigned int num_frames);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string serial_number;
|
||||
std::mutex lock;
|
||||
HXQS_HIDAPI_WRAPPER hidapi_wrapper;
|
||||
|
||||
void SendEOT(uint8_t frame_count);
|
||||
void SendToRegister(uint8_t reg, uint8_t param1, uint8_t param2);
|
||||
};
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
/*-----------------------------------------*\
|
||||
| HyperXQuadcastSControllerDetect.cpp |
|
||||
| |
|
||||
| Implementation for the HyperX |
|
||||
| Quadcast S RGB microphone |
|
||||
| |
|
||||
| Matt Silva (thesilvanator) 2022 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "Detector.h"
|
||||
#include "HyperXQuadcastSController.h"
|
||||
#include "RGBController.h"
|
||||
#include "RGBController_HyperXQuadcastS.h"
|
||||
#include <vector>
|
||||
#include <LogManager.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <hidapi/hidapi.h>
|
||||
|
||||
|
||||
#define HYPERX_QS_VID_NA 0x0951
|
||||
#define HYPERX_QS_PID_NA 0x171F
|
||||
#define HYPERX_QS_VID_EU 0x03F0
|
||||
#define HYPERX_QS_PID_EU 0x0F8B
|
||||
|
||||
const char* name = "HyperX Quadcast S";
|
||||
|
||||
#ifdef __linux__
|
||||
void FindAndAddHyperXQuadcastSDevice(unsigned int vid, unsigned int pid,
|
||||
HXQS_HIDAPI_WRAPPER wrapper,
|
||||
std::vector<RGBController*>& rgb_controllers)
|
||||
{
|
||||
std::string path;
|
||||
|
||||
hid_device_info* devs = NULL;
|
||||
hid_device *dev = NULL;
|
||||
|
||||
HyperXQuadcastSController* controller;
|
||||
RGBController_HyperXQuadcastS* rgb_controller;
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Iterate over devices with corresponding |
|
||||
| VID and PID and check if there is one |
|
||||
| with interface 0 as that is what we use |
|
||||
\*-----------------------------------------*/
|
||||
if(!(devs = wrapper.enumerate(vid, pid)))
|
||||
{
|
||||
LOG_DEBUG("[%s] Dynamic call to hid_enumerate failed or couldn't find a device (Linux only)", name);
|
||||
return;
|
||||
}
|
||||
|
||||
hid_device_info *curr = devs;
|
||||
while(curr)
|
||||
{
|
||||
if(curr->interface_number == 0)
|
||||
{
|
||||
path = curr->path;
|
||||
LOG_DEBUG("[%s] Found device with correct 0 interface (Linux only): %s", name, path.c_str());
|
||||
break;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
wrapper.free_enumeration(devs);
|
||||
|
||||
if(!curr)
|
||||
{
|
||||
LOG_ERROR("[%s] Unable to find device with 0 interface (Linux only)", name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(!(dev = wrapper.open_path(path.c_str())))
|
||||
{
|
||||
LOG_ERROR("[%s] Dynamic call to hid_open_path failed (Linux only)", name);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("[%s] Sucessfully opened device as a hidapi_device (Linux only)", name);
|
||||
|
||||
|
||||
controller = new HyperXQuadcastSController(dev, wrapper, path);
|
||||
rgb_controller = new RGBController_HyperXQuadcastS(controller);
|
||||
|
||||
rgb_controller->name = name;
|
||||
rgb_controllers.push_back(rgb_controller);
|
||||
}
|
||||
|
||||
void DetectHyperXQuadcastSControllers(std::vector<RGBController*>& rgb_controllers)
|
||||
{
|
||||
/*-----------------------------------------*\
|
||||
| Dynamically load hidapi-libusb and setup |
|
||||
| wrapper for Linux platforms |
|
||||
\*-----------------------------------------*/
|
||||
void* dyn_handle = NULL;
|
||||
HXQS_HIDAPI_WRAPPER wrapper;
|
||||
|
||||
if(!(dyn_handle = dlopen("libhidapi-libusb.so", RTLD_NOW | RTLD_NODELETE | RTLD_DEEPBIND)))
|
||||
{
|
||||
LOG_ERROR("[%s] Couldn't dynamically load hidapi-libusb (Linux only): %s", name, dlerror());
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper =
|
||||
{
|
||||
.dyn_handle = dyn_handle,
|
||||
.send_feature_report = (HXQS_Report_Send_t) dlsym(dyn_handle,"hid_send_feature_report"),
|
||||
.get_feature_report = (HXQS_Report_Get_t) dlsym(dyn_handle,"hid_get_feature_report"),
|
||||
.get_serial_num_string = (HXQS_Get_Serial_t) dlsym(dyn_handle,"hid_get_serial_number_string"),
|
||||
.open_path = (HXQS_hid_open_path_t) dlsym(dyn_handle,"hid_open_path"),
|
||||
.enumerate = (HXQS_hid_enumerate_t) dlsym(dyn_handle,"hid_enumerate"),
|
||||
.free_enumeration = (HXQS_hid_free_enumeration_t) dlsym(dyn_handle,"hid_free_enumeration"),
|
||||
.close = (HXQS_hid_close_t) dlsym(dyn_handle,"hid_close"),
|
||||
.error = (HXQS_hid_error_t) dlsym(dyn_handle,"hid_free_enumeration")
|
||||
};
|
||||
|
||||
if(!(wrapper.send_feature_report && wrapper.get_feature_report &&
|
||||
wrapper.open_path && wrapper.enumerate && wrapper.free_enumeration &&
|
||||
wrapper.close && wrapper.error && wrapper.get_serial_num_string))
|
||||
{
|
||||
LOG_ERROR("[%s] Couldn't dynamically load one of hidapi-libusb functions for the wrapper (Linux only)", name);
|
||||
return;
|
||||
}
|
||||
|
||||
FindAndAddHyperXQuadcastSDevice(HYPERX_QS_VID_NA, HYPERX_QS_PID_NA, wrapper, rgb_controllers);
|
||||
FindAndAddHyperXQuadcastSDevice(HYPERX_QS_VID_EU, HYPERX_QS_PID_EU, wrapper, rgb_controllers);
|
||||
}
|
||||
|
||||
REGISTER_DETECTOR("HyperX Quadcast S", DetectHyperXQuadcastSControllers);
|
||||
#else
|
||||
void DetectHyperXQuadcastSControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device *dev = hid_open_path(info->path);
|
||||
|
||||
if(!dev)
|
||||
{
|
||||
LOG_ERROR("[%s] Unable to open device via hid_open_path(%s): %ls", name.c_str(), info->path, hid_error(dev));
|
||||
return;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Setup wrapper for Windows platforms just |
|
||||
| using the already linked in hidapi |
|
||||
| functions |
|
||||
\*-----------------------------------------*/
|
||||
HXQS_HIDAPI_WRAPPER wrapper =
|
||||
{
|
||||
NULL, // dyn_handle
|
||||
hid_send_feature_report,
|
||||
hid_get_feature_report,
|
||||
hid_get_serial_number_string,
|
||||
hid_open_path,
|
||||
hid_enumerate,
|
||||
hid_free_enumeration,
|
||||
hid_close,
|
||||
hid_error
|
||||
};
|
||||
|
||||
|
||||
HyperXQuadcastSController* controller = new HyperXQuadcastSController(dev, wrapper, info->path);
|
||||
RGBController_HyperXQuadcastS *rgb_controller = new RGBController_HyperXQuadcastS(controller);
|
||||
|
||||
rgb_controller->name = name;
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
|
||||
}
|
||||
REGISTER_HID_DETECTOR_IPU("HyperX Quadcast S", DetectHyperXQuadcastSControllers, HYPERX_QS_VID_NA, HYPERX_QS_PID_NA, 0, 0xFF90, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IPU("HyperX Quadcast S", DetectHyperXQuadcastSControllers, HYPERX_QS_VID_EU, HYPERX_QS_PID_EU, 0, 0xFF90, 0xFF00);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
/*-----------------------------------------*\
|
||||
| RGBController_HyperXQuadcastS.cpp |
|
||||
| |
|
||||
| Implementation for the HyperX |
|
||||
| Quadcast S RGB microphone |
|
||||
| |
|
||||
| Matt Silva (thesilvanator) 2022 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name HyperX Quadcast S
|
||||
@type USB
|
||||
@save :white_check_mark:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectHyperXQuadcastSControllers
|
||||
@comment The HyperX Quadcast S has a manufacturer issue
|
||||
with the interface it uses (0) for controlling its RGB.
|
||||
HID requires that any HID interface have at least one
|
||||
Interrupt IN endpoint; however, the HXQS does not,
|
||||
even though its interface reports itelf as hid and
|
||||
responds to hid requests. As such Linux doesn't bind
|
||||
to the usbhid driver and it goes undetected by
|
||||
hidapi-hidraw. Windows does detect it as hid and hidapi
|
||||
finds and interacts with it just fine. To work around
|
||||
the Linux issue, hidapi-libusb is loaded dynamically
|
||||
using dlopen/dlsym as hidapi using a libusb backend is
|
||||
able to find the device and interact with it. This
|
||||
requires that you have support for dlopen/dlsym on your
|
||||
Linux platform as well as hidapi-libusb (and libusb)
|
||||
libraries installed in the standard dynamic library
|
||||
path.
|
||||
|
||||
The controller for this device has a wrapper for hidapi
|
||||
functions so that the controller can be the same across
|
||||
all platforms, but call the correct underlying functions
|
||||
that are defined in the detector under an #ifdef
|
||||
for that platform.
|
||||
|
||||
Additionally, hidapi-libusb has an error that causes
|
||||
hid_close() to hang on this device, see:
|
||||
https://github.com/libusb/hidapi/issues/456
|
||||
This will be fixed on newer versions of hidapi-libusb,
|
||||
but until then, OpenRGB will hang/crash if you try to
|
||||
rescan devices once a HXQS has been detected during
|
||||
program session.
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_HyperXQuadcastS.h"
|
||||
#include <LogManager.h>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
RGBController_HyperXQuadcastS::RGBController_HyperXQuadcastS(HyperXQuadcastSController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = "HyperX QuadcastS Device";
|
||||
vendor = "HyperX";
|
||||
type = DEVICE_TYPE_MICROPHONE;
|
||||
description = "HyperX QuadcastS Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
Direct.brightness_min = 0;
|
||||
Direct.brightness_max = 100;
|
||||
Direct.colors.push_back(ToRGBColor(0xFF,0,0)); // Top LED
|
||||
Direct.colors.push_back(ToRGBColor(0xFF,0,0)); // Bot LED
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.flags = MODE_FLAG_MANUAL_SAVE;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
Off.colors.push_back(ToRGBColor(0,0,0)); // Top LED
|
||||
Off.colors.push_back(ToRGBColor(0,0,0)); // Bot LED
|
||||
modes.push_back(Off);
|
||||
|
||||
SetupZones();
|
||||
|
||||
keepalive_thread_run = 1;
|
||||
keepalive_thread = new std::thread(&RGBController_HyperXQuadcastS::KeepaliveThread, this);
|
||||
};
|
||||
|
||||
RGBController_HyperXQuadcastS::~RGBController_HyperXQuadcastS()
|
||||
{
|
||||
keepalive_thread_run = 0;
|
||||
keepalive_thread->join();
|
||||
delete keepalive_thread;
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_HyperXQuadcastS::SetupZones()
|
||||
{
|
||||
led* Top = new led();
|
||||
led* Bot = new led();
|
||||
Top->name = std::string("Top");
|
||||
Top->value = 0;
|
||||
Bot->name = std::string("Bottom");
|
||||
Bot->value = 1;
|
||||
leds.push_back(*Top);
|
||||
leds.push_back(*Bot);
|
||||
|
||||
zone* Mic = new zone();
|
||||
Mic->name = std::string("Microphone");
|
||||
Mic->type = ZONE_TYPE_LINEAR;
|
||||
Mic->leds_min = 2;
|
||||
Mic->leds_max = 2;
|
||||
Mic->leds_count = 2;
|
||||
Mic->matrix_map = NULL;
|
||||
zones.push_back(*Mic);
|
||||
|
||||
SetupColors();
|
||||
|
||||
// make starting colors be the default starting
|
||||
// colors for direct
|
||||
colors = modes[HXQS_MODE_DIRECT].colors;
|
||||
}
|
||||
|
||||
void RGBController_HyperXQuadcastS::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RGBController_HyperXQuadcastS::DeviceUpdateLEDs()
|
||||
{
|
||||
last_update_time = std::chrono::steady_clock::now();
|
||||
controller->SendDirect(colors);
|
||||
}
|
||||
void RGBController_HyperXQuadcastS::UpdateZoneLEDs(int zone)
|
||||
{
|
||||
|
||||
}
|
||||
void RGBController_HyperXQuadcastS::UpdateSingleLED(int led)
|
||||
{
|
||||
|
||||
}
|
||||
void RGBController_HyperXQuadcastS::DeviceUpdateMode()
|
||||
{
|
||||
switch (active_mode)
|
||||
{
|
||||
case HXQS_MODE_DIRECT:
|
||||
// make current colors this modes colors, in this case,
|
||||
// the preserved direct colors from before switching off
|
||||
colors = modes[active_mode].colors;
|
||||
|
||||
break;
|
||||
case HXQS_MODE_OFF:
|
||||
modes[HXQS_MODE_DIRECT].colors = colors; // preserve directs previous colours
|
||||
colors = modes[active_mode].colors; // make current colors this modes colors
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_HyperXQuadcastS::DeviceSaveMode()
|
||||
{
|
||||
LOG_DEBUG("[%s] Saving current direct colors to device", name.c_str());
|
||||
controller->SaveColors(colors,1);
|
||||
}
|
||||
|
||||
void RGBController_HyperXQuadcastS::KeepaliveThread()
|
||||
{
|
||||
while(keepalive_thread_run.load())
|
||||
{
|
||||
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
|
||||
{
|
||||
UpdateLEDs();
|
||||
}
|
||||
std::this_thread::sleep_for(15ms);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*-----------------------------------------*\
|
||||
| RGBController_HyperXQuadcastS.h |
|
||||
| |
|
||||
| Implementation for the HyperX |
|
||||
| Quadcast S RGB microphone |
|
||||
| |
|
||||
| Matt Silva (thesilvanator) 2022 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
#include <chrono>
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "HyperXQuadcastSController.h"
|
||||
|
||||
enum
|
||||
{
|
||||
HXQS_MODE_DIRECT = 0,
|
||||
HXQS_MODE_OFF = 1,
|
||||
};
|
||||
|
||||
class RGBController_HyperXQuadcastS : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_HyperXQuadcastS(HyperXQuadcastSController* controller_ptr);
|
||||
~RGBController_HyperXQuadcastS();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
void DeviceSaveMode();
|
||||
|
||||
void KeepaliveThread();
|
||||
|
||||
private:
|
||||
HyperXQuadcastSController* controller;
|
||||
std::thread* keepalive_thread;
|
||||
std::atomic<bool> keepalive_thread_run;
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
|
||||
};
|
||||
|
|
@ -131,6 +131,7 @@ INCLUDEPATH +=
|
|||
Controllers/HyperXKeyboardController/ \
|
||||
Controllers/HyperXMouseController/ \
|
||||
Controllers/HyperXMousematController/ \
|
||||
Controllers/HyperXQuadcastController/ \
|
||||
Controllers/IntelArcA770LEController/ \
|
||||
Controllers/IonicoController/ \
|
||||
Controllers/LEDStripController/ \
|
||||
|
|
@ -457,6 +458,8 @@ HEADERS +=
|
|||
Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.h \
|
||||
Controllers/HyperXMousematController/HyperXMousematController.h \
|
||||
Controllers/HyperXMousematController/RGBController_HyperXMousemat.h \
|
||||
Controllers/HyperXQuadcastController/HyperXQuadcastSController.h \
|
||||
Controllers/HyperXQuadcastController/RGBController_HyperXQuadcastS.h \
|
||||
Controllers/IntelArcA770LEController/IntelArcA770LEController.h \
|
||||
Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.h \
|
||||
Controllers/IonicoController/IonicoController.h \
|
||||
|
|
@ -1045,6 +1048,9 @@ SOURCES +=
|
|||
Controllers/HyperXMousematController/HyperXMousematController.cpp \
|
||||
Controllers/HyperXMousematController/HyperXMousematControllerDetect.cpp \
|
||||
Controllers/HyperXMousematController/RGBController_HyperXMousemat.cpp \
|
||||
Controllers/HyperXQuadcastController/HyperXQuadcastSController.cpp \
|
||||
Controllers/HyperXQuadcastController/HyperXQuadcastSControllerDetect.cpp \
|
||||
Controllers/HyperXQuadcastController/RGBController_HyperXQuadcastS.cpp \
|
||||
Controllers/IntelArcA770LEController/IntelArcA770LEController.cpp \
|
||||
Controllers/IntelArcA770LEController/IntelArcA770LEControllerDetect.cpp \
|
||||
Controllers/IonicoController/IonicoController.cpp \
|
||||
|
|
@ -1619,6 +1625,7 @@ contains(QMAKE_PLATFORM, linux) {
|
|||
-lmbedx509 \
|
||||
-lmbedtls \
|
||||
-lmbedcrypto \
|
||||
-ldl \
|
||||
|
||||
COMPILER_VERSION = $$system($$QMAKE_CXX " -dumpversion")
|
||||
if (!versionAtLeast(COMPILER_VERSION, "9")) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue