Publish LumaOps source

This commit is contained in:
LumaOps release export
2026-09-03 01:18:36 +02:00
commit 7f1c0e5f71
2363 changed files with 501543 additions and 0 deletions
@@ -0,0 +1,206 @@
/*---------------------------------------------------------*\
| HyperXMicrophoneController.cpp |
| |
| Driver for HyperX microphone |
| |
| Matt Silva (thesilvanator) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXMicrophoneController.h"
#include "StringUtils.h"
using namespace std::chrono_literals;
HyperXMicrophoneController::HyperXMicrophoneController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, std::string path, std::string dev_name)
{
wrapper = hid_wrapper;
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXMicrophoneController::~HyperXMicrophoneController()
{
lock.lock();
if(dev)
{
wrapper.hid_close(dev);
}
lock.unlock();
}
std::string HyperXMicrophoneController::GetDeviceLocation()
{
return(location);
}
std::string HyperXMicrophoneController::GetNameString()
{
return(name);
}
std::string HyperXMicrophoneController::GetSerialString()
{
wchar_t serial_string[128];
int ret = wrapper.hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXMicrophoneController::SaveColors(std::vector<RGBColor> colors, unsigned int num_frames)
{
unsigned int num_color_packets = 0;
unsigned int frame = 0;
unsigned char color[HYPERX_QUADCAST_S_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, HYPERX_QUADCAST_S_PACKET_SIZE);
unsigned int i = 0;
while(i < 8 && frame < num_frames)
{
int index = HYPERX_QUADCAST_S_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);
wrapper.hid_send_feature_report(dev, color, HYPERX_QUADCAST_S_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 HyperXMicrophoneController::SendDirect(std::vector<RGBColor> colors)
{
/*---------------------------------------------------------*\
| Verify colors size |
\*---------------------------------------------------------*/
if(colors.size() != 2)
{
return;
}
RGBColor c1 = colors[0];
RGBColor c2 = colors[1];
uint8_t buffer[HYPERX_QUADCAST_S_PACKET_SIZE];
/*---------------------------------------------------------*\
| Colour packet |
\*---------------------------------------------------------*/
memset(buffer, 0, HYPERX_QUADCAST_S_PACKET_SIZE);
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();
wrapper.hid_send_feature_report(dev, buffer, HYPERX_QUADCAST_S_PACKET_SIZE);
std::this_thread::sleep_for(15ms);
SendToRegister(0xF2, 0, 1);
lock.unlock();
}
void HyperXMicrophoneController::SendEOT(uint8_t frame_count)
{
uint8_t buffer[HYPERX_QUADCAST_S_PACKET_SIZE];
memset(buffer, 0, HYPERX_QUADCAST_S_PACKET_SIZE);
buffer[0x01] = 0x08;
buffer[0x3C] = 0x28;
buffer[0x3D] = frame_count;
buffer[0x3E] = 0x00;
buffer[0x3F] = 0xAA;
buffer[0x40] = 0x55;
wrapper.hid_send_feature_report(dev, buffer, HYPERX_QUADCAST_S_PACKET_SIZE);
std::this_thread::sleep_for(15ms);
}
void HyperXMicrophoneController::SendToRegister(uint8_t reg, uint8_t param1, uint8_t param2)
{
uint8_t buffer[HYPERX_QUADCAST_S_PACKET_SIZE];
memset(buffer, 0, HYPERX_QUADCAST_S_PACKET_SIZE);
buffer[0x01] = 0x04;
buffer[0x02] = reg; // 0xF2 Apply, 0x53 Save
buffer[0x08] = param1;
buffer[0x09] = param2;
wrapper.hid_send_feature_report(dev, buffer, HYPERX_QUADCAST_S_PACKET_SIZE);
std::this_thread::sleep_for(15ms);
}
@@ -0,0 +1,43 @@
/*---------------------------------------------------------*\
| HyperXMicrophoneController.cpp |
| |
| Driver for HyperX microphone |
| |
| Matt Silva (thesilvanator) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "hidapi_wrapper.h"
#include "RGBController.h"
#define HYPERX_QUADCAST_S_PACKET_SIZE 64 + 1
#define HYPERX_QUADCAST_S_FRAME_SIZE 8
class HyperXMicrophoneController
{
public:
HyperXMicrophoneController(hidapi_wrapper hid_wrapper, hid_device* dev, std::string path, std::string dev_name);
~HyperXMicrophoneController();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SendDirect(std::vector<RGBColor> color_data);
void SaveColors(std::vector<RGBColor> colors, unsigned int num_frames);
private:
hidapi_wrapper wrapper;
hid_device* dev;
std::string location;
std::mutex lock;
std::string name;
void SendEOT(uint8_t frame_count);
void SendToRegister(uint8_t reg, uint8_t param1, uint8_t param2);
};
@@ -0,0 +1,54 @@
/*---------------------------------------------------------*\
| HyperXMicrophoneControllerDetect.cpp |
| |
| Detector for HyperX microphone |
| |
| Matt Silva (thesilvanator) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "Detector.h"
#include "HyperXMicrophoneController.h"
#include "RGBController_HyperXMicrophone.h"
#include "hidapi_wrapper.h"
/*-----------------------------------------------------*\
| HyperX microphone vendor and product IDs |
\*-----------------------------------------------------*/
#define HYPERX_VID 0x0951
#define HYPERX_HP_VID 0x03F0
#define HYPERX_QS_PID 0x171F
#define HYPERX_QS_PID_HP_1 0x0F8B
#define HYPERX_QS_PID_HP_2 0x068C
#define HYPERX_QS_PID_HP_3 0x0294
#define HYPERX_QS_PID_HP_4 0x028C
#define HYPERX_QS_PID_HP_5 0x048C
#define HYPERX_QS_PID_HP_6 0x0D8B
#define HYPERX_DUOCAST_PID 0x098C
void DetectHyperXMicrophoneControllers(hidapi_wrapper wrapper, hid_device_info* info, const std::string& name)
{
hid_device* dev = wrapper.hid_open_path(info->path);
if(dev)
{
HyperXMicrophoneController* controller = new HyperXMicrophoneController(wrapper, dev, info->path, name);
RGBController_HyperXMicrophone *rgb_controller = new RGBController_HyperXMicrophone(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_VID, HYPERX_QS_PID, 0);//, 0xFF90, 0xFF00);
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_1, 0);//, 0xFF90, 0xFF00);
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_2, 0);//, 0xFF90, 0xFF00);
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_3, 0);//, 0xFF90, 0xFF00);
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_4, 0);//, 0xFF90, 0xFF00);
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_5, 0);//, 0xFF90, 0xFF00);
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_6, 0);//, 0xFF90, 0xFF00);
REGISTER_HID_WRAPPED_DETECTOR_I("HyperX DuoCast", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_DUOCAST_PID, 0);//, 0xFF90, 0xFF00);
@@ -0,0 +1,155 @@
/*---------------------------------------------------------*\
| RGBController_HyperXMicrophone.cpp |
| |
| RGBController for HyperX microphone |
| |
| Matt Silva (thesilvanator) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
/**------------------------------------------------------------------*\
@name HyperX Quadcast S
@type USB
@save :white_check_mark:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXMicrophoneControllers
@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_HyperXMicrophone.h"
#include <LogManager.h>
using namespace std::chrono_literals;
RGBController_HyperXMicrophone::RGBController_HyperXMicrophone(HyperXMicrophoneController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_MICROPHONE;
description = "HyperX Microphone Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXMicrophone::KeepaliveThread, this);
};
RGBController_HyperXMicrophone::~RGBController_HyperXMicrophone()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
delete controller;
}
void RGBController_HyperXMicrophone::SetupZones()
{
led Top;
Top.name = "Top";
Top.value = 0;
led Bot;
Bot.name = "Bottom";
Bot.value = 1;
leds.push_back(Top);
leds.push_back(Bot);
zone Mic;
Mic.name = "Microphone";
Mic.type = ZONE_TYPE_SINGLE;
Mic.leds_min = 2;
Mic.leds_max = 2;
Mic.leds_count = 2;
Mic.matrix_map = nullptr;
zones.push_back(Mic);
SetupColors();
}
void RGBController_HyperXMicrophone::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXMicrophone::DeviceUpdateLEDs()
{
last_update_time = std::chrono::steady_clock::now();
controller->SendDirect(colors);
}
void RGBController_HyperXMicrophone::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXMicrophone::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXMicrophone::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
void RGBController_HyperXMicrophone::DeviceSaveMode()
{
LOG_DEBUG("[%s] Saving current direct colors to device", name.c_str());
controller->SaveColors(colors, 1);
}
void RGBController_HyperXMicrophone::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,42 @@
/*---------------------------------------------------------*\
| RGBController_HyperXMicrophone.h |
| |
| RGBController for HyperX microphone |
| |
| Matt Silva (thesilvanator) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXMicrophoneController.h"
class RGBController_HyperXMicrophone : public RGBController
{
public:
RGBController_HyperXMicrophone(HyperXMicrophoneController* controller_ptr);
~RGBController_HyperXMicrophone();
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:
HyperXMicrophoneController* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};