Publish LumaOps source
This commit is contained in:
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user