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,183 @@
/*---------------------------------------------------------*\
| HyperXAlloyElite2Controller.cpp |
| |
| Driver for HyperX Alloy Elite 2 keyboard |
| |
| KundaPanda (vojdo) 02 Apr 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXAlloyElite2Controller.h"
#include "StringUtils.h"
/*-----------------------------------------*\
| Skip these indices in the color output |
\*-----------------------------------------*/
static const unsigned int SKIP_INDICES[] = { 23, 29, 41, 47, 70, 71, 76, 77, 87, 88, 93, 99, 100, 102, 108, 113 };
HyperXAlloyElite2Controller::HyperXAlloyElite2Controller(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXAlloyElite2Controller::~HyperXAlloyElite2Controller()
{
hid_close(dev);
}
std::string HyperXAlloyElite2Controller::GetDeviceLocation()
{
return("HID " + location);
}
std::string HyperXAlloyElite2Controller::GetNameString()
{
return(name);
}
std::string HyperXAlloyElite2Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXAlloyElite2Controller::SetLEDsDirect(const std::vector<RGBColor>& colors)
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Variables to keep track of color sending and skipping |
\*-----------------------------------------------------*/
size_t buf_idx = 1;
size_t color_idx = 0;
size_t packets_sent = 0;
size_t skipped = 0;
const unsigned int* skip_idx = &SKIP_INDICES[0];
/*-----------------------------------------------------*\
| Initialize direct control |
\*-----------------------------------------------------*/
SendDirectInitialization();
/*-----------------------------------------------------*\
| Continue filling and sending packets while color data |
| remains |
\*-----------------------------------------------------*/
while(color_idx < colors.size())
{
/*-------------------------------------------------*\
| Packets have colors in groups of 4 bytes, with |
| the first byte being 0x81 and then R, G, B. |
\*-------------------------------------------------*/
buf[buf_idx] = 0x81;
/*-------------------------------------------------*\
| If at a skipped index, add null data to packet |
| and increment skipped count and index |
| Otherwise, copy color data to buffer and increment|
| color index |
\*-------------------------------------------------*/
if(*skip_idx == color_idx + skipped)
{
buf[buf_idx + 1] = 0;
buf[buf_idx + 2] = 0;
buf[buf_idx + 3] = 0;
skip_idx++;
if(skip_idx >= SKIP_INDICES + sizeof(SKIP_INDICES) / sizeof(unsigned int))
{
skip_idx = SKIP_INDICES;
}
skipped++;
}
else
{
buf[buf_idx + 1] = RGBGetRValue(colors[color_idx]);
buf[buf_idx + 2] = RGBGetGValue(colors[color_idx]);
buf[buf_idx + 3] = RGBGetBValue(colors[color_idx]);
color_idx++;
}
/*-------------------------------------------------*\
| Increment packet buffer index by 4 bytes |
\*-------------------------------------------------*/
buf_idx += 4;
/*-------------------------------------------------*\
| If the packet buffer is full, send it and reset |
| buffer indexing |
| OR |
| If all colors have been filled into the buffer, |
| send the packet |
\*-------------------------------------------------*/
if((buf_idx >= sizeof(buf)) || (color_idx == colors.size()))
{
/*---------------------------------------------*\
| Send packet |
\*---------------------------------------------*/
hid_send_feature_report(dev, buf, sizeof(buf));
/*---------------------------------------------*\
| Zero out buffer and reset index |
\*---------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
buf_idx = 1;
/*---------------------------------------------*\
| Increment packet counter |
\*---------------------------------------------*/
packets_sent++;
}
}
/*-----------------------------------------------------*\
| Send empty packets until 9 total packets have been |
| sent |
\*-----------------------------------------------------*/
for(size_t remaining_packets = 0; packets_sent + remaining_packets < 9; remaining_packets++)
{
hid_send_feature_report(dev, buf, sizeof(buf));
}
}
void HyperXAlloyElite2Controller::SendDirectInitialization()
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Select Profile packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x00;
buf[0x01] = 0x04;
buf[0x02] = 0xF2;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 65);
}
@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| HyperXAlloyElite2Controller.h |
| |
| Driver for HyperX Alloy Elite 2 keyboard |
| |
| KundaPanda (vojdo) 02 Apr 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
class HyperXAlloyElite2Controller
{
public:
HyperXAlloyElite2Controller(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXAlloyElite2Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetLEDsDirect(const std::vector<RGBColor>& colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirectInitialization();
};
@@ -0,0 +1,346 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyElite2.cpp |
| |
| RGBController for HyperX Alloy Elite 2 keyboard |
| |
| KundaPanda (vojdo) 02 Apr 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXAlloyElite2.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[8][22] =
{
{ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 104, 107, 108, 98, NA, NA },
{ 110, 111, 112, 113, NA, 114, 115, 116, NA, 117, 118, 119, 120, NA, 121, 122, 123, NA, 124, 125, 126, 127 },
{ 0, 12, 18, 23, 28, NA, 34, 39, 44, 50, 56, 62, 66, 70, NA, 76, 80, 85, NA, NA, NA, NA },
{ 1, 7, 13, 19, 24, 29, 35, 40, 45, 51, 57, 63, 67, 71, NA, 77, 81, 86, 89, 94, 99, 105 },
{ 2, NA, 8, 14, 20, 25, 30, 36, 41, 46, 52, 58, 64, 68, 72, 78, 82, 87, 90, 95, 100, 106 },
{ 3, NA, 9, 15, 21, 26, 31, 37, 42, 47, 53, 59, 65, 69, 73, NA, NA, NA, 91, 96, 101, NA },
{ 4, 6, NA, 10, 16, 22, 27, 32, 38, 43, 48, 54, 60, 74, NA, NA, 83, NA, 92, 97, 102, 109 },
{ 5, 11, 17, NA, NA, NA, NA, 33, NA, NA, NA, 49, 61, 55, 75, 79, 84, 88, 93, NA, 103, NA }
};
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const unsigned int zone_sizes[] =
{
128,
};
// ISO 6, 75, !80
// ANSI !6, !75, 80
static const char *led_names[] =
{
KEY_EN_ESCAPE,
KEY_EN_BACK_TICK,
KEY_EN_TAB,
KEY_EN_CAPS_LOCK,
KEY_EN_LEFT_SHIFT,
KEY_EN_LEFT_CONTROL,
KEY_EN_ISO_BACK_SLASH,
KEY_EN_1,
KEY_EN_Q,
KEY_EN_A,
KEY_EN_Z,
KEY_EN_LEFT_WINDOWS,
KEY_EN_F1,
KEY_EN_2,
KEY_EN_W,
KEY_EN_S,
KEY_EN_X,
KEY_EN_LEFT_ALT,
KEY_EN_F2,
KEY_EN_3,
KEY_EN_E,
KEY_EN_D,
KEY_EN_C,
// Skip index 23
KEY_EN_F3,
KEY_EN_4,
KEY_EN_R,
KEY_EN_F,
KEY_EN_V,
// Skip index 29
KEY_EN_F4,
KEY_EN_5,
KEY_EN_T,
KEY_EN_G,
KEY_EN_B,
KEY_EN_SPACE,
KEY_EN_F5,
KEY_EN_6,
KEY_EN_Y,
KEY_EN_H,
KEY_EN_N,
// Skip index 41
KEY_EN_F6,
KEY_EN_7,
KEY_EN_U,
KEY_EN_J,
KEY_EN_M,
// Skip index 47
KEY_EN_F7,
KEY_EN_8,
KEY_EN_I,
KEY_EN_K,
KEY_EN_COMMA,
KEY_EN_RIGHT_ALT,
KEY_EN_F8,
KEY_EN_9,
KEY_EN_O,
KEY_EN_L,
KEY_EN_PERIOD,
KEY_EN_MENU,
KEY_EN_F9,
KEY_EN_0,
KEY_EN_P,
KEY_EN_SEMICOLON,
KEY_EN_FORWARD_SLASH,
KEY_EN_RIGHT_WINDOWS,
KEY_EN_F10,
KEY_EN_MINUS,
KEY_EN_LEFT_BRACKET,
KEY_EN_QUOTE,
// Skip index 70
// Skip index 71
KEY_EN_F11,
KEY_EN_EQUALS,
KEY_EN_RIGHT_BRACKET,
KEY_EN_POUND,
// Skip index 76
KEY_EN_F12,
KEY_EN_BACKSPACE,
KEY_EN_ANSI_BACK_SLASH,
KEY_EN_ANSI_ENTER,
KEY_EN_RIGHT_SHIFT,
KEY_EN_RIGHT_CONTROL,
KEY_EN_PRINT_SCREEN,
KEY_EN_INSERT,
KEY_EN_DELETE,
// Skip index 87
// Skip index 88
KEY_EN_LEFT_ARROW,
KEY_EN_SCROLL_LOCK,
KEY_EN_HOME,
KEY_EN_END,
// Skip index 93
KEY_EN_UP_ARROW,
KEY_EN_DOWN_ARROW,
KEY_EN_PAUSE_BREAK,
KEY_EN_PAGE_UP,
KEY_EN_PAGE_DOWN,
// Skip index 99
// Skip index 100
KEY_EN_RIGHT_ARROW,
// Skip index 102
KEY_EN_NUMPAD_LOCK,
KEY_EN_NUMPAD_7,
KEY_EN_NUMPAD_4,
KEY_EN_NUMPAD_1,
KEY_EN_NUMPAD_0,
// Skip index 108
KEY_EN_NUMPAD_DIVIDE,
KEY_EN_NUMPAD_8,
KEY_EN_NUMPAD_5,
KEY_EN_NUMPAD_2,
// Skip index 113
KEY_EN_MEDIA_MUTE, // Last multimedia key
KEY_EN_NUMPAD_TIMES,
KEY_EN_NUMPAD_9,
KEY_EN_NUMPAD_6,
KEY_EN_NUMPAD_3,
KEY_EN_NUMPAD_PERIOD,
KEY_EN_MEDIA_PREVIOUS, // First multimedia key
KEY_EN_NUMPAD_MINUS,
KEY_EN_NUMPAD_PLUS,
KEY_EN_MEDIA_PLAY_PAUSE, // Second multimedia key
KEY_EN_MEDIA_NEXT, // Third multimedia key
KEY_EN_NUMPAD_ENTER,
"RGB Strip 1",
"RGB Strip 2",
"RGB Strip 3",
"RGB Strip 4",
"RGB Strip 5",
"RGB Strip 6",
"RGB Strip 7",
"RGB Strip 8",
"RGB Strip 9",
"RGB Strip 10",
"RGB Strip 11",
"RGB Strip 12",
"RGB Strip 13",
"RGB Strip 14",
"RGB Strip 15",
"RGB Strip 16",
"RGB Strip 17",
"RGB Strip 18",
};
/**------------------------------------------------------------------*\
@name HyperX Alloy Elite 2
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectHyperXAlloyElite2
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXAlloyElite2::RGBController_HyperXAlloyElite2(HyperXAlloyElite2Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
description = "HyperX Alloy Elite 2 Keyboard Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
/*-----------------------------------------------------*\
| The Corsair Lighting Node Pro requires a packet within|
| 20 seconds of sending the lighting change in order |
| to not revert back into rainbow mode. Start a thread |
| to continuously send a keepalive packet every 5s |
\*-----------------------------------------------------*/
keepalive_thread_run = true;
keepalive_thread = new std::thread(&RGBController_HyperXAlloyElite2::KeepaliveThreadFunction, this);
}
RGBController_HyperXAlloyElite2::~RGBController_HyperXAlloyElite2()
{
keepalive_thread_run = false;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != nullptr)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXAlloyElite2::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
zone new_zone;
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
new_zone.leds_min = zone_sizes[zone_idx];
new_zone.leds_max = zone_sizes[zone_idx];
new_zone.leds_count = zone_sizes[zone_idx];
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = new matrix_map_type;
new_zone.matrix_map->height = 8;
new_zone.matrix_map->width = 22;
new_zone.matrix_map->map = (unsigned int *)&matrix_map;
}
else
{
new_zone.matrix_map = nullptr;
}
zones.push_back(new_zone);
total_led_count += zone_sizes[zone_idx];
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXAlloyElite2::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXAlloyElite2::DeviceUpdateLEDs()
{
last_update_time = std::chrono::steady_clock::now();
if(active_mode == 0)
{
controller->SetLEDsDirect(colors);
}
}
void RGBController_HyperXAlloyElite2::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyElite2::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyElite2::DeviceUpdateMode()
{
}
void RGBController_HyperXAlloyElite2::KeepaliveThreadFunction()
{
while(keepalive_thread_run)
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(1000))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(50ms);
}
}
@@ -0,0 +1,43 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyElite2.h |
| |
| RGBController for HyperX Alloy Elite 2 keyboard |
| |
| KundaPanda (vojdo) 02 Apr 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <atomic>
#include <chrono>
#include <thread>
#include "RGBController.h"
#include "HyperXAlloyElite2Controller.h"
class RGBController_HyperXAlloyElite2 : public RGBController
{
public:
RGBController_HyperXAlloyElite2(HyperXAlloyElite2Controller* controller_ptr);
~RGBController_HyperXAlloyElite2();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThreadFunction();
private:
HyperXAlloyElite2Controller* controller;
std::atomic<bool> keepalive_thread_run;
std::thread* keepalive_thread;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -0,0 +1,509 @@
/*---------------------------------------------------------*\
| HyperXAlloyEliteController.cpp |
| |
| Driver for HyperX Alloy Elite keyboard |
| |
| Adam Honse (CalcProgrammer1) 30 Jan 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXAlloyEliteController.h"
#include "StringUtils.h"
using namespace std::chrono_literals;
static unsigned int keys[] = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x20, 0x21, 0x22,
0x23, 0x24, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0x34, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3E, 0x3F, 0x41,
0x44, 0x45, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x51, 0x54, 0x55,
0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5E, 0x5F, 0x61, 0x64, 0x65, 0x68, 0x69, 0x6A,
0x6B, 0x6C, 0x6E, 0x6F, 0x74, 0x75, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E,
0x7F, 0x81, 0x84, 0x85, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91,
0x94, 0x95 };
static unsigned int extended_red[] = {0x08, 0x48, 0x88, 0x09, 0x89, 0x0A, 0x8A, 0x0B, 0x8B, 0x0C, 0x8C, 0x0D, 0x8D, 0x0E, 0x8F, 0x8E, 0x0F, 0x4F, 0x92, 0x13, 0x93, 0x12 };
static unsigned int extended_grn[] = {0x29, 0x28, 0x78, 0x19, 0x79, 0x1A, 0x7A, 0x1B, 0x7B, 0x1C, 0x7C, 0x1D, 0x7D, 0x1E, 0x6E, 0x7E, 0x1F, 0x6F, 0x82, 0x23, 0x83, 0x22 };
static unsigned int extended_blu[] = {0x39, 0x38, 0x68, 0x3A, 0x69, 0x2A, 0x6A, 0x2B, 0x6B, 0x2C, 0x6C, 0x2D, 0x6D, 0x2E, 0x5E, 0x5D, 0x2F, 0x5F, 0x72, 0x33, 0x73, 0x32 };
HyperXAlloyEliteController::HyperXAlloyEliteController(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXAlloyEliteController::~HyperXAlloyEliteController()
{
hid_close(dev);
}
std::string HyperXAlloyEliteController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string HyperXAlloyEliteController::GetNameString()
{
return(name);
}
std::string HyperXAlloyEliteController::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXAlloyEliteController::SetMode
(
unsigned char mode,
unsigned char direction,
unsigned char speed,
std::vector<RGBColor> colors
)
{
unsigned char color_mode;
unsigned char mode_colors[9];
active_mode = mode;
active_direction = direction;
active_speed = speed;
memset(mode_colors, 0x00, sizeof(mode_colors));
switch(colors.size())
{
default:
case 0:
color_mode = HYPERX_ALLOY_ELITE_COLOR_MODE_SPECTRUM;
break;
case 1:
color_mode = HYPERX_ALLOY_ELITE_COLOR_MODE_SINGLE;
mode_colors[0] = RGBGetRValue(colors[0]);
mode_colors[1] = RGBGetGValue(colors[0]);
mode_colors[2] = RGBGetBValue(colors[0]);
break;
case 2:
color_mode = HYPERX_ALLOY_ELITE_COLOR_MODE_DUAL;
mode_colors[3] = RGBGetRValue(colors[0]);
mode_colors[4] = RGBGetGValue(colors[0]);
mode_colors[5] = RGBGetBValue(colors[0]);
mode_colors[6] = RGBGetRValue(colors[1]);
mode_colors[7] = RGBGetGValue(colors[1]);
mode_colors[8] = RGBGetBValue(colors[1]);
break;
}
SendEffect
(
0x01,
active_mode,
active_direction,
HYPERX_ALLOY_ELITE_REACTIVE_MODE_NONE,
active_speed,
color_mode,
mode_colors[0],
mode_colors[1],
mode_colors[2],
mode_colors[3],
mode_colors[4],
mode_colors[5],
mode_colors[6],
mode_colors[7],
mode_colors[8]
);
std::this_thread::sleep_for(100ms);
}
void HyperXAlloyEliteController::SetLEDsDirect(std::vector<RGBColor> colors)
{
unsigned char red_color_data[106];
unsigned char grn_color_data[106];
unsigned char blu_color_data[106];
unsigned char ext_color_data[150];
for(std::size_t i = 0; i < 106; i++)
{
red_color_data[i] = RGBGetRValue(colors[i]);
grn_color_data[i] = RGBGetGValue(colors[i]);
blu_color_data[i] = RGBGetBValue(colors[i]);
}
for(std::size_t i = 0; i < 22; i++)
{
ext_color_data[extended_red[i]] = RGBGetRValue(colors[i + 106]);
ext_color_data[extended_grn[i]] = RGBGetGValue(colors[i + 106]);
ext_color_data[extended_blu[i]] = RGBGetBValue(colors[i + 106]);
}
SendDirect
(
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_RED,
red_color_data
);
std::this_thread::sleep_for(5ms);
SendDirect
(
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_GREEN,
grn_color_data
);
std::this_thread::sleep_for(5ms);
SendDirect
(
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_BLUE,
blu_color_data
);
std::this_thread::sleep_for(5ms);
SendDirectExtended
(
ext_color_data
);
}
void HyperXAlloyEliteController::SetLEDs(std::vector<RGBColor> colors)
{
unsigned char red_color_data[106];
unsigned char grn_color_data[106];
unsigned char blu_color_data[106];
unsigned char ext_color_data[150];
for(std::size_t i = 0; i < 106; i++)
{
red_color_data[i] = RGBGetRValue(colors[i]);
grn_color_data[i] = RGBGetGValue(colors[i]);
blu_color_data[i] = RGBGetBValue(colors[i]);
}
for(std::size_t i = 0; i < 22; i++)
{
ext_color_data[extended_red[i]] = RGBGetRValue(colors[i + 106]);
ext_color_data[extended_grn[i]] = RGBGetGValue(colors[i + 106]);
ext_color_data[extended_blu[i]] = RGBGetBValue(colors[i + 106]);
}
SendColor
(
0x01,
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_RED,
red_color_data
);
std::this_thread::sleep_for(5ms);
SendColor
(
0x01,
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_GREEN,
grn_color_data
);
std::this_thread::sleep_for(5ms);
SendColor
(
0x01,
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_BLUE,
blu_color_data
);
std::this_thread::sleep_for(5ms);
SendExtendedColor
(
0x01,
ext_color_data
);
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
void HyperXAlloyEliteController::SelectProfile
(
unsigned char profile
)
{
unsigned char buf[264];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Select Profile packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x07;
buf[0x01] = 0x01;
buf[0x02] = profile;
buf[0x06] = 0x03;
buf[0x07] = 0x01;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 264);
}
void HyperXAlloyEliteController::SendEffect
(
unsigned char profile,
unsigned char mode,
unsigned char direction,
unsigned char reactive_mode,
unsigned char speed,
unsigned char color_mode,
unsigned char red_single,
unsigned char grn_single,
unsigned char blu_single,
unsigned char red_dual_1,
unsigned char grn_dual_1,
unsigned char blu_dual_1,
unsigned char red_dual_2,
unsigned char grn_dual_2,
unsigned char blu_dual_2
)
{
unsigned char buf[264];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Effect packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x07;
buf[0x01] = HYPERX_ALLOY_ELITE_PACKET_ID_SET_EFFECT;
buf[0x02] = profile;
/*-----------------------------------------------------*\
| Set mode |
\*-----------------------------------------------------*/
buf[0x09] = 0x01;
buf[0x0A] = mode;
/*-----------------------------------------------------*\
| Set direction |
\*-----------------------------------------------------*/
buf[0x0D] = direction;
buf[0x0E] = direction;
/*-----------------------------------------------------*\
| Set reactive mode |
\*-----------------------------------------------------*/
buf[0x1B] = reactive_mode;
buf[0x1C] = reactive_mode;
buf[0x1D] = reactive_mode;
buf[0x1E] = reactive_mode;
buf[0x1F] = reactive_mode;
buf[0x20] = reactive_mode;
buf[0x21] = reactive_mode;
buf[0x22] = reactive_mode;
/*-----------------------------------------------------*\
| Set mode-specific colors |
\*-----------------------------------------------------*/
buf[0x29] = red_single;
buf[0x41] = grn_single;
buf[0x59] = blu_single;
buf[0x2A] = red_dual_1;
buf[0x42] = grn_dual_1;
buf[0x5A] = blu_dual_1;
buf[0x2B] = red_dual_2;
buf[0x43] = grn_dual_2;
buf[0x5B] = blu_dual_2;
buf[0x6B] = 0x09;
buf[0x6C] = 0x09;
buf[0x6D] = 0x05;
buf[0x6E] = 0x05;
buf[0x6F] = 0x06;
buf[0x70] = 0x05;
/*-----------------------------------------------------*\
| Set speed |
\*-----------------------------------------------------*/
buf[0x71] = speed;
buf[0x72] = 0x09;
/*-----------------------------------------------------*\
| Set color mode |
\*-----------------------------------------------------*/
buf[0x73] = color_mode;
buf[0x74] = color_mode;
buf[0x75] = color_mode;
buf[0x76] = color_mode;
buf[0x77] = color_mode;
buf[0x78] = color_mode;
buf[0x79] = color_mode;
buf[0x7A] = color_mode;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 264);
}
void HyperXAlloyEliteController::SendColor
(
unsigned char profile,
unsigned char color_channel,
unsigned char* color_data
)
{
unsigned char buf[264];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Color packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x07;
buf[0x01] = HYPERX_ALLOY_ELITE_PACKET_ID_SET_COLOR;
buf[0x02] = profile;
buf[0x03] = color_channel;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for(int i = 0; i < 106; i++)
{
buf[keys[i]] = color_data[i];
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 264);
}
void HyperXAlloyEliteController::SendExtendedColor
(
unsigned char profile,
unsigned char* color_data
)
{
unsigned char buf[264];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Color packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x07;
buf[0x01] = HYPERX_ALLOY_ELITE_PACKET_ID_SET_COLOR;
buf[0x02] = profile;
buf[0x03] = HYPERX_ALLOY_ELITE_COLOR_CHANNEL_EXTENDED;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for(int i = 0x08; i < 0x94; i++)
{
buf[i] = color_data[i];
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 264);
}
void HyperXAlloyEliteController::SendDirect
(
unsigned char color_channel,
unsigned char* color_data
)
{
unsigned char buf[264];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x07;
buf[0x01] = HYPERX_ALLOY_ELITE_PACKET_ID_DIRECT;
buf[0x02] = color_channel;
buf[0x03] = 0xA0;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for(int i = 0; i < 106; i++)
{
buf[keys[i]] = color_data[i];
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 264);
}
void HyperXAlloyEliteController::SendDirectExtended
(
unsigned char* color_data
)
{
unsigned char buf[264];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x07;
buf[0x01] = HYPERX_ALLOY_ELITE_PACKET_ID_DIRECT;
buf[0x02] = HYPERX_ALLOY_ELITE_COLOR_CHANNEL_EXTENDED;
buf[0x03] = 0xA0;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for(int i = 0x08; i < 0x94; i++)
{
buf[i] = color_data[i];
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 264);
}
@@ -0,0 +1,142 @@
/*---------------------------------------------------------*\
| HyperXAlloyEliteController.h |
| |
| Driver for HyperX Alloy Elite keyboard |
| |
| Adam Honse (CalcProgrammer1) 30 Jan 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
enum
{
HYPERX_ALLOY_ELITE_PACKET_ID_SET_EFFECT = 0x02, /* Set profile effect packet */
HYPERX_ALLOY_ELITE_PACKET_ID_SET_COLOR = 0x06, /* Set profile color packet */
HYPERX_ALLOY_ELITE_PACKET_ID_DIRECT = 0x16, /* Direct control packet */
};
enum
{
HYPERX_ALLOY_ELITE_DIRECTION_RIGHT = 0x00,
HYPERX_ALLOY_ELITE_DIRECTION_LEFT = 0x01,
HYPERX_ALLOY_ELITE_DIRECTION_UP = 0x02,
HYPERX_ALLOY_ELITE_DIRECTION_DOWN = 0x03,
HYPERX_ALLOY_ELITE_DIRECTION_IN = 0x04,
HYPERX_ALLOY_ELITE_DIRECTION_OUT = 0x05
};
enum
{
HYPERX_ALLOY_ELITE_MODE_WAVE = 0x00,
HYPERX_ALLOY_ELITE_MODE_STATIC = 0x01,
HYPERX_ALLOY_ELITE_MODE_BREATHING = 0x02,
};
enum
{
HYPERX_ALLOY_ELITE_REACTIVE_MODE_TRIGGER = 0x03,
HYPERX_ALLOY_ELITE_REACTIVE_MODE_EXPLOSION = 0x04,
HYPERX_ALLOY_ELITE_REACTIVE_MODE_HYPERX_FLAME = 0x05,
HYPERX_ALLOY_ELITE_REACTIVE_MODE_NONE = 0xFF
};
enum
{
HYPERX_ALLOY_ELITE_COLOR_MODE_SINGLE = 0x00,
HYPERX_ALLOY_ELITE_COLOR_MODE_DUAL = 0x01,
HYPERX_ALLOY_ELITE_COLOR_MODE_SPECTRUM = 0x02
};
enum
{
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_RED = 0x01,
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_GREEN = 0x02,
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_BLUE = 0x03,
HYPERX_ALLOY_ELITE_COLOR_CHANNEL_EXTENDED = 0x04
};
class HyperXAlloyEliteController
{
public:
HyperXAlloyEliteController(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXAlloyEliteController();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetMode
(
unsigned char mode,
unsigned char direction,
unsigned char speed,
std::vector<RGBColor> colors
);
void SetLEDsDirect(std::vector<RGBColor> colors);
void SetLEDs(std::vector<RGBColor> colors);
private:
hid_device* dev;
unsigned char active_mode;
unsigned char active_direction;
unsigned char active_speed;
std::string location;
std::string name;
void SelectProfile
(
unsigned char profile
);
void SendEffect
(
unsigned char profile,
unsigned char mode,
unsigned char direction,
unsigned char reactive_mode,
unsigned char speed,
unsigned char color_mode,
unsigned char red_single,
unsigned char grn_single,
unsigned char blu_single,
unsigned char red_dual_1,
unsigned char grn_dual_1,
unsigned char blu_dual_1,
unsigned char red_dual_2,
unsigned char grn_dual_2,
unsigned char blu_dual_2
);
void SendColor
(
unsigned char profile,
unsigned char color_channel,
unsigned char* color_data
);
void SendExtendedColor
(
unsigned char profile,
unsigned char* color_data
);
void SendDirect
(
unsigned char color_channel,
unsigned char* color_data
);
void SendDirectExtended
(
unsigned char* color_data
);
};
@@ -0,0 +1,371 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyElite.cpp |
| |
| RGBController for HyperX Alloy Elite keyboard |
| |
| Adam Honse (CalcProgrammer1) 02 Feb 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXAlloyElite.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[6][23] =
{ { 0, NA, 16, 30, 44, 54, NA, 65, 75, 84, 95, NA, 8, 23 , 38, 6 , 22, 36, 49, NA, NA, NA, NA },
{ 1, 17, 31, 45, 55, 66, 76, 85, 96, 9, 24, NA, 39, 7 , 37, NA , 60, 70, 80, 52, 63, 73, 82 },
{ 2, NA, 18, 32, 46, 56, NA, 67, 77, 86, 97, 10, 25, 40 , 90, 101, 50, 61, 71, 51, 62, 72, 93 },
{ 3, NA, 19, 33, 47, 57, NA, 68, 78, 87, 98, 11, 26, 41 , 28, 14 , NA, NA, NA, 92, 103, 53, NA },
{ 4, 20, 34, 48, 58, 69, NA, 79, NA, 88, 99, 12, 27, 42 , 81, NA , NA, 102, NA, 64, 74, 83, 104 },
{ 5, 21, 35, NA, NA, NA, NA, 59, NA, NA, NA, NA, 89, 100, 13, 91 , 15, 29, 43, 94, NA, 105, NA } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
"RGB Strip",
"Media Keys"
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
ZONE_TYPE_LINEAR,
ZONE_TYPE_SINGLE
};
static const unsigned int zone_sizes[] =
{
106,
18,
4
};
static const char *led_names[] =
{
KEY_EN_ESCAPE,
KEY_EN_BACK_TICK,
KEY_EN_TAB,
KEY_EN_CAPS_LOCK,
KEY_EN_LEFT_SHIFT,
KEY_EN_LEFT_CONTROL,
KEY_EN_F12,
KEY_EN_EQUALS,
KEY_EN_F9,
KEY_EN_9,
KEY_EN_O,
KEY_EN_L,
KEY_EN_COMMA,
KEY_EN_MENU,
KEY_EN_ISO_ENTER,
KEY_EN_LEFT_ARROW,
KEY_EN_F1,
KEY_EN_1,
KEY_EN_Q,
KEY_EN_A,
KEY_EN_ISO_BACK_SLASH,
KEY_EN_LEFT_WINDOWS,
KEY_EN_PRINT_SCREEN,
KEY_EN_F10,
KEY_EN_0,
KEY_EN_P,
KEY_EN_SEMICOLON,
KEY_EN_PERIOD,
KEY_EN_ANSI_ENTER,
KEY_EN_DOWN_ARROW,
KEY_EN_F2,
KEY_EN_2,
KEY_EN_W,
KEY_EN_S,
KEY_EN_Z,
KEY_EN_LEFT_ALT,
KEY_EN_SCROLL_LOCK,
KEY_EN_BACKSPACE,
KEY_EN_F11,
KEY_EN_MINUS,
KEY_EN_LEFT_BRACKET,
KEY_EN_QUOTE,
KEY_EN_FORWARD_SLASH,
KEY_EN_RIGHT_ARROW,
KEY_EN_F3,
KEY_EN_3,
KEY_EN_E,
KEY_EN_D,
KEY_EN_X,
KEY_EN_PAUSE_BREAK,
KEY_EN_DELETE,
KEY_EN_NUMPAD_7,
KEY_EN_NUMPAD_LOCK,
KEY_EN_NUMPAD_6,
KEY_EN_F4,
KEY_EN_4,
KEY_EN_R,
KEY_EN_F,
KEY_EN_C,
KEY_EN_SPACE,
KEY_EN_INSERT,
KEY_EN_END,
KEY_EN_NUMPAD_8,
KEY_EN_NUMPAD_DIVIDE,
KEY_EN_NUMPAD_1,
KEY_EN_F5,
KEY_EN_5,
KEY_EN_T,
KEY_EN_G,
KEY_EN_V,
KEY_EN_HOME,
KEY_EN_PAGE_DOWN,
KEY_EN_NUMPAD_9,
KEY_EN_NUMPAD_TIMES,
KEY_EN_NUMPAD_2,
KEY_EN_F6,
KEY_EN_6,
KEY_EN_Y,
KEY_EN_H,
KEY_EN_B,
KEY_EN_PAGE_UP,
KEY_EN_RIGHT_SHIFT,
KEY_EN_NUMPAD_MINUS,
KEY_EN_NUMPAD_3,
KEY_EN_F7,
KEY_EN_7,
KEY_EN_U,
KEY_EN_J,
KEY_EN_N,
KEY_EN_RIGHT_ALT,
KEY_EN_RIGHT_BRACKET,
KEY_EN_RIGHT_CONTROL,
KEY_EN_NUMPAD_4,
KEY_EN_NUMPAD_PLUS,
KEY_EN_NUMPAD_0,
KEY_EN_F8,
KEY_EN_8,
KEY_EN_I,
KEY_EN_K,
KEY_EN_M,
KEY_EN_RIGHT_WINDOWS,
KEY_EN_ANSI_BACK_SLASH,
KEY_EN_UP_ARROW,
KEY_EN_NUMPAD_5,
KEY_EN_NUMPAD_ENTER,
KEY_EN_NUMPAD_PERIOD,
"RGB Strip 1",
"RGB Strip 2",
"RGB Strip 3",
"RGB Strip 4",
"RGB Strip 5",
"RGB Strip 6",
"RGB Strip 7",
"RGB Strip 8",
"RGB Strip 9",
"RGB Strip 10",
"RGB Strip 11",
"RGB Strip 12",
"RGB Strip 13",
"RGB Strip 14",
"RGB Strip 15",
"RGB Strip 16",
"RGB Strip 17",
"RGB Strip 18",
KEY_EN_MEDIA_PREVIOUS,
KEY_EN_MEDIA_PLAY_PAUSE,
KEY_EN_MEDIA_NEXT,
KEY_EN_MEDIA_MUTE
};
/**------------------------------------------------------------------*\
@name HyperX Alloy Elite
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectHyperXAlloyElite
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXAlloyElite::RGBController_HyperXAlloyElite(HyperXAlloyEliteController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
description = "HyperX Alloy Elite Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = HYPERX_ALLOY_ELITE_MODE_STATIC;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Static;
Static.name = "Static";
Static.value = HYPERX_ALLOY_ELITE_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE;
Static.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Static);
mode Wave;
Wave.name = "Wave";
Wave.value = HYPERX_ALLOY_ELITE_MODE_WAVE;
Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE;
Wave.speed_min = 0x00;
Wave.speed_max = 0x09;
Wave.color_mode = MODE_COLORS_NONE;
Wave.speed = 0x09;
Wave.direction = MODE_DIRECTION_LEFT;
modes.push_back(Wave);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = HYPERX_ALLOY_ELITE_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE;
Breathing.speed_min = 0x00;
Breathing.speed_max = 0x09;
Breathing.colors_min = 1;
Breathing.colors_max = 2;
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
Breathing.speed = 0x09;
Breathing.colors.resize(2);
modes.push_back(Breathing);
SetupZones();
/*-----------------------------------------------------*\
| The HyperX Alloy Elite requires a steady stream of |
| packets in order to not revert out of direct mode. |
| Start a thread to continuously refresh the device |
\*-----------------------------------------------------*/
keepalive_thread_run = true;
keepalive_thread = new std::thread(&RGBController_HyperXAlloyElite::KeepaliveThreadFunction, this);
}
RGBController_HyperXAlloyElite::~RGBController_HyperXAlloyElite()
{
keepalive_thread_run = false;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXAlloyElite::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 3; zone_idx++)
{
zone new_zone;
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
new_zone.leds_min = zone_sizes[zone_idx];
new_zone.leds_max = zone_sizes[zone_idx];
new_zone.leds_count = zone_sizes[zone_idx];
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = new matrix_map_type;
new_zone.matrix_map->height = 6;
new_zone.matrix_map->width = 23;
new_zone.matrix_map->map = (unsigned int *)&matrix_map;
}
else
{
new_zone.matrix_map = NULL;
}
zones.push_back(new_zone);
total_led_count += zone_sizes[zone_idx];
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXAlloyElite::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXAlloyElite::DeviceUpdateLEDs()
{
last_update_time = std::chrono::steady_clock::now();
if(active_mode == 0)
{
controller->SetLEDsDirect(colors);
}
else
{
controller->SetLEDs(colors);
}
}
void RGBController_HyperXAlloyElite::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyElite::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyElite::DeviceUpdateMode()
{
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
{
controller->SetMode(modes[active_mode].value, modes[active_mode].direction, modes[active_mode].speed, modes[active_mode].colors);
}
else
{
std::vector<RGBColor> temp_colors;
controller->SetMode(modes[active_mode].value, modes[active_mode].direction, modes[active_mode].speed, temp_colors);
}
}
void RGBController_HyperXAlloyElite::KeepaliveThreadFunction()
{
while(keepalive_thread_run)
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);;
}
}
@@ -0,0 +1,43 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyElite.h |
| |
| RGBController for HyperX Alloy Elite keyboard |
| |
| Adam Honse (CalcProgrammer1) 02 Feb 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <atomic>
#include <chrono>
#include <thread>
#include "RGBController.h"
#include "HyperXAlloyEliteController.h"
class RGBController_HyperXAlloyElite : public RGBController
{
public:
RGBController_HyperXAlloyElite(HyperXAlloyEliteController* controller_ptr);
~RGBController_HyperXAlloyElite();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThreadFunction();
private:
HyperXAlloyEliteController* controller;
std::atomic<bool> keepalive_thread_run;
std::thread* keepalive_thread;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -0,0 +1,136 @@
/*---------------------------------------------------------*\
| HyperXAlloyFPSController.cpp |
| |
| Driver for HyperX Alloy FPS keyboard |
| |
| Adam Honse (CalcProgrammer1) 30 Jan 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXAlloyFPSController.h"
#include "StringUtils.h"
using namespace std::chrono_literals;
static unsigned int keys[] = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x20, 0x21, 0x22,
0x23, 0x24, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0x34, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3E, 0x3F, 0x41,
0x44, 0x45, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x51, 0x54, 0x55,
0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5E, 0x5F, 0x61, 0x64, 0x65, 0x68, 0x69, 0x6A,
0x6B, 0x6C, 0x6E, 0x6F, 0x74, 0x75, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E,
0x7F, 0x81, 0x84, 0x85, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91,
0x94, 0x95 };
HyperXAlloyFPSController::HyperXAlloyFPSController(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXAlloyFPSController::~HyperXAlloyFPSController()
{
hid_close(dev);
}
std::string HyperXAlloyFPSController::GetDeviceLocation()
{
return("HID: " + location);
}
std::string HyperXAlloyFPSController::GetNameString()
{
return(name);
}
std::string HyperXAlloyFPSController::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXAlloyFPSController::SetLEDsDirect(std::vector<RGBColor> colors)
{
unsigned char red_color_data[106];
unsigned char grn_color_data[106];
unsigned char blu_color_data[106];
for(std::size_t i = 0; i < 106; i++)
{
red_color_data[i] = RGBGetRValue(colors[i]);
grn_color_data[i] = RGBGetGValue(colors[i]);
blu_color_data[i] = RGBGetBValue(colors[i]);
}
SendDirect
(
HYPERX_ALLOY_FPS_COLOR_CHANNEL_RED,
red_color_data
);
std::this_thread::sleep_for(10ms);
SendDirect
(
HYPERX_ALLOY_FPS_COLOR_CHANNEL_GREEN,
grn_color_data
);
std::this_thread::sleep_for(10ms);
SendDirect
(
HYPERX_ALLOY_FPS_COLOR_CHANNEL_BLUE,
blu_color_data
);
}
/*-------------------------------------------------------------------------------------------------*\
| Private packet sending functions. |
\*-------------------------------------------------------------------------------------------------*/
void HyperXAlloyFPSController::SendDirect
(
unsigned char color_channel,
unsigned char* color_data
)
{
unsigned char buf[264];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x07;
buf[0x01] = HYPERX_ALLOY_FPS_PACKET_ID_DIRECT;
buf[0x02] = color_channel;
buf[0x03] = 0xA0;
/*-----------------------------------------------------*\
| Fill in color data |
\*-----------------------------------------------------*/
for(int i = 0; i < 106; i++)
{
buf[keys[i]] = color_data[i];
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 264);
}
@@ -0,0 +1,52 @@
/*---------------------------------------------------------*\
| HyperXAlloyFPSController.h |
| |
| Driver for HyperX Alloy FPS keyboard |
| |
| Adam Honse (CalcProgrammer1) 30 Jan 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
enum
{
HYPERX_ALLOY_FPS_PACKET_ID_DIRECT = 0x16, /* Direct control packet */
};
enum
{
HYPERX_ALLOY_FPS_COLOR_CHANNEL_RED = 0x01,
HYPERX_ALLOY_FPS_COLOR_CHANNEL_GREEN = 0x02,
HYPERX_ALLOY_FPS_COLOR_CHANNEL_BLUE = 0x03
};
class HyperXAlloyFPSController
{
public:
HyperXAlloyFPSController(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXAlloyFPSController();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirect
(
unsigned char color_channel,
unsigned char* color_data
);
};
@@ -0,0 +1,300 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyFPS.cpp |
| |
| RGBController for HyperX Alloy FPS keyboard |
| |
| Adam Honse (CalcProgrammer1) 02 Feb 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXAlloyFPS.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[6][23] =
{ { 0, NA, 16, 30, 44, 54, NA, 65, 75, 84, 95, NA, 8, 23 , 38, 6 , 22, 36, 49, NA, NA, NA, NA },
{ 1, 17, 31, 45, 55, 66, 76, 85, 96, 9, 24, NA, 39, 7 , 37, NA , 60, 70, 80, 52, 63, 73, 82 },
{ 2, NA, 18, 32, 46, 56, NA, 67, 77, 86, 97, 10, 25, 40 , 90, 101, 50, 61, 71, 51, 62, 72, 93 },
{ 3, NA, 19, 33, 47, 57, NA, 68, 78, 87, 98, 11, 26, 41 , 28, 14 , NA, NA, NA, 92, 103, 53, NA },
{ 4, 20, 34, 48, 58, 69, NA, 79, NA, 88, 99, 12, 27, 42 , 81, NA , NA, 102, NA, 64, 74, 83, 104 },
{ 5, 21, 35, NA, NA, NA, NA, 59, NA, NA, NA, NA, 89, 100, 13, 91 , 15, 29, 43, 94, NA, 105, NA } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX
};
static const unsigned int zone_sizes[] =
{
106
};
static const char *led_names[] =
{
KEY_EN_ESCAPE,
KEY_EN_BACK_TICK,
KEY_EN_TAB,
KEY_EN_CAPS_LOCK,
KEY_EN_LEFT_SHIFT,
KEY_EN_LEFT_CONTROL,
KEY_EN_F12,
KEY_EN_EQUALS,
KEY_EN_F9,
KEY_EN_9,
KEY_EN_O,
KEY_EN_L,
KEY_EN_COMMA,
KEY_EN_MENU,
KEY_EN_ISO_ENTER,
KEY_EN_LEFT_ARROW,
KEY_EN_F1,
KEY_EN_1,
KEY_EN_Q,
KEY_EN_A,
KEY_EN_ISO_BACK_SLASH,
KEY_EN_LEFT_WINDOWS,
KEY_EN_PRINT_SCREEN,
KEY_EN_F10,
KEY_EN_0,
KEY_EN_P,
KEY_EN_SEMICOLON,
KEY_EN_PERIOD,
KEY_EN_ANSI_ENTER,
KEY_EN_DOWN_ARROW,
KEY_EN_F2,
KEY_EN_2,
KEY_EN_W,
KEY_EN_S,
KEY_EN_Z,
KEY_EN_LEFT_ALT,
KEY_EN_SCROLL_LOCK,
KEY_EN_BACKSPACE,
KEY_EN_F11,
KEY_EN_MINUS,
KEY_EN_LEFT_BRACKET,
KEY_EN_QUOTE,
KEY_EN_FORWARD_SLASH,
KEY_EN_RIGHT_ARROW,
KEY_EN_F3,
KEY_EN_3,
KEY_EN_E,
KEY_EN_D,
KEY_EN_X,
KEY_EN_PAUSE_BREAK,
KEY_EN_DELETE,
KEY_EN_NUMPAD_7,
KEY_EN_NUMPAD_LOCK,
KEY_EN_NUMPAD_6,
KEY_EN_F4,
KEY_EN_4,
KEY_EN_R,
KEY_EN_F,
KEY_EN_C,
KEY_EN_SPACE,
KEY_EN_INSERT,
KEY_EN_END,
KEY_EN_NUMPAD_8,
KEY_EN_NUMPAD_DIVIDE,
KEY_EN_NUMPAD_1,
KEY_EN_F5,
KEY_EN_5,
KEY_EN_T,
KEY_EN_G,
KEY_EN_V,
KEY_EN_HOME,
KEY_EN_PAGE_DOWN,
KEY_EN_NUMPAD_9,
KEY_EN_NUMPAD_TIMES,
KEY_EN_NUMPAD_2,
KEY_EN_F6,
KEY_EN_6,
KEY_EN_Y,
KEY_EN_H,
KEY_EN_B,
KEY_EN_PAGE_UP,
KEY_EN_RIGHT_SHIFT,
KEY_EN_NUMPAD_MINUS,
KEY_EN_NUMPAD_3,
KEY_EN_F7,
KEY_EN_7,
KEY_EN_U,
KEY_EN_J,
KEY_EN_N,
KEY_EN_RIGHT_ALT,
KEY_EN_RIGHT_BRACKET,
KEY_EN_RIGHT_CONTROL,
KEY_EN_NUMPAD_4,
KEY_EN_NUMPAD_PLUS,
KEY_EN_NUMPAD_0,
KEY_EN_F8,
KEY_EN_8,
KEY_EN_I,
KEY_EN_K,
KEY_EN_M,
KEY_EN_RIGHT_WINDOWS,
KEY_EN_ANSI_BACK_SLASH,
KEY_EN_UP_ARROW,
KEY_EN_NUMPAD_5,
KEY_EN_NUMPAD_ENTER,
KEY_EN_NUMPAD_PERIOD
};
/**------------------------------------------------------------------*\
@name HyperX Alloy FPS
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXAlloyFPS
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXAlloyFPS::RGBController_HyperXAlloyFPS(HyperXAlloyFPSController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
description = "HyperX Alloy FPS Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
/*-----------------------------------------------------*\
| The HyperX Alloy FPS requires a steady stream of |
| packets in order to not revert out of direct mode. |
| Start a thread to continuously refresh the device |
\*-----------------------------------------------------*/
keepalive_thread_run = true;
keepalive_thread = new std::thread(&RGBController_HyperXAlloyFPS::KeepaliveThreadFunction, this);
}
RGBController_HyperXAlloyFPS::~RGBController_HyperXAlloyFPS()
{
keepalive_thread_run = false;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXAlloyFPS::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
zone new_zone;
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
new_zone.leds_min = zone_sizes[zone_idx];
new_zone.leds_max = zone_sizes[zone_idx];
new_zone.leds_count = zone_sizes[zone_idx];
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = new matrix_map_type;
new_zone.matrix_map->height = 6;
new_zone.matrix_map->width = 23;
new_zone.matrix_map->map = (unsigned int *)&matrix_map;
}
else
{
new_zone.matrix_map = NULL;
}
zones.push_back(new_zone);
total_led_count += zone_sizes[zone_idx];
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXAlloyFPS::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXAlloyFPS::DeviceUpdateLEDs()
{
last_update_time = std::chrono::steady_clock::now();
if(active_mode == 0)
{
controller->SetLEDsDirect(colors);
}
}
void RGBController_HyperXAlloyFPS::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyFPS::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyFPS::DeviceUpdateMode()
{
}
void RGBController_HyperXAlloyFPS::KeepaliveThreadFunction()
{
while(keepalive_thread_run)
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);;
}
}
@@ -0,0 +1,43 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyFPS.h |
| |
| RGBController for HyperX Alloy FPS keyboard |
| |
| Adam Honse (CalcProgrammer1) 02 Feb 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <atomic>
#include <chrono>
#include <thread>
#include "RGBController.h"
#include "HyperXAlloyFPSController.h"
class RGBController_HyperXAlloyFPS : public RGBController
{
public:
RGBController_HyperXAlloyFPS(HyperXAlloyFPSController* controller_ptr);
~RGBController_HyperXAlloyFPS();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThreadFunction();
private:
HyperXAlloyFPSController* controller;
std::atomic<bool> keepalive_thread_run;
std::thread* keepalive_thread;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -0,0 +1,148 @@
/*---------------------------------------------------------*\
| HyperXAlloyOrigins60and65Controller.cpp |
| |
| Driver for HyperX Alloy Origins 60 and 65 keyboard |
| |
| Derek Huber 18 Mar 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXAlloyOrigins60and65Controller.h"
#include "StringUtils.h"
HyperXAlloyOrigins60and65Controller::HyperXAlloyOrigins60and65Controller(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXAlloyOrigins60and65Controller::~HyperXAlloyOrigins60and65Controller()
{
hid_close(dev);
}
std::string HyperXAlloyOrigins60and65Controller::GetDeviceLocation()
{
return("HID " + location);
}
std::string HyperXAlloyOrigins60and65Controller::GetNameString()
{
return(name);
}
std::string HyperXAlloyOrigins60and65Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXAlloyOrigins60and65Controller::SetLEDsDirect(std::vector<RGBColor> colors)
{
/*-----------------------------------------------------*\
| Set up variables to track progress of color transmit |
| Do this after inserting blanks |
\*-----------------------------------------------------*/
int colors_to_send = (int)colors.size();
int colors_sent = 0;
SendDirectInitialization();
for(int pkt_idx = 0; pkt_idx < 5; pkt_idx++)
{
if(colors_to_send > 16)
{
SendDirectColorPacket(&colors[colors_sent], 16);
colors_sent += 16;
colors_to_send -= 16;
}
else if(colors_to_send > 0)
{
SendDirectColorPacket(&colors[colors_sent], colors_to_send);
colors_sent += colors_to_send;
colors_to_send -= colors_to_send;
}
else
{
RGBColor temp = 0x00000000;
SendDirectColorPacket(&temp, 1);
}
}
}
void HyperXAlloyOrigins60and65Controller::SendDirectInitialization()
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x00;
buf[0x01] = 0x04;
buf[0x02] = 0xF2;
buf[0x09] = 0x05;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 65);
}
void HyperXAlloyOrigins60and65Controller::SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count
)
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x00;
/*-----------------------------------------------------*\
| The maximum number of colors per packet is 16 |
\*-----------------------------------------------------*/
if(color_count > 16)
{
color_count = 16;
}
/*-----------------------------------------------------*\
| Copy in color data |
\*-----------------------------------------------------*/
for(unsigned int color_idx = 0; color_idx < color_count; color_idx++)
{
buf[(color_idx * 4) + 1] = 0x81;
buf[(color_idx * 4) + 2] = RGBGetRValue(color_data[color_idx]);
buf[(color_idx * 4) + 3] = RGBGetGValue(color_data[color_idx]);
buf[(color_idx * 4) + 4] = RGBGetBValue(color_data[color_idx]);
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 65);
}
@@ -0,0 +1,41 @@
/*---------------------------------------------------------*\
| HyperXAlloyOrigins60and65Controller.h |
| |
| Driver for HyperX Alloy Origins 60 and 65 keyboard |
| |
| Derek Huber 18 Mar 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
class HyperXAlloyOrigins60and65Controller
{
public:
HyperXAlloyOrigins60and65Controller(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXAlloyOrigins60and65Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirectInitialization();
void SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count
);
};
@@ -0,0 +1,362 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyOrigins60and65.cpp |
| |
| RGBController for HyperX Alloy Origins 60 and 65 |
| keyboard |
| |
| Derek Huber 18 Mar 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXAlloyOrigins60and65.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map_60[5][14] =
{ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15 },
{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 },
{ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, NA, 43 },
{ 44, NA, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, NA, 57 },
{ 58, 59, 60, 61, NA, NA, 62, NA, NA, 63, 64, 65, 66, 70 } };
static unsigned int matrix_map_65[5][15] =
{ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 69 },
{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 70 },
{ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, NA, 43, 71 },
{ 44, NA, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 57, 73, 72 },
{ 58, 59, 60, 61, NA, NA, 62, NA, NA, 63, 64, 68, 74, 75, 76 } };
static const char *led_names_60[] =
{
// First row
KEY_EN_UNUSED,
KEY_EN_ESCAPE,
KEY_EN_1,
KEY_EN_2,
KEY_EN_3,
KEY_EN_4,
KEY_EN_5,
KEY_EN_6,
KEY_EN_7,
KEY_EN_8,
KEY_EN_9,
KEY_EN_0,
KEY_EN_MINUS,
KEY_EN_EQUALS,
KEY_EN_UNUSED,
KEY_EN_BACKSPACE,
// Second row
KEY_EN_TAB,
KEY_EN_Q,
KEY_EN_W,
KEY_EN_E,
KEY_EN_R,
KEY_EN_T,
KEY_EN_Y,
KEY_EN_U,
KEY_EN_I,
KEY_EN_O,
KEY_EN_P,
KEY_EN_LEFT_BRACKET,
KEY_EN_RIGHT_BRACKET,
KEY_EN_ANSI_BACK_SLASH,
// Third row
KEY_EN_CAPS_LOCK,
KEY_EN_A,
KEY_EN_S,
KEY_EN_D,
KEY_EN_F,
KEY_EN_G,
KEY_EN_H,
KEY_EN_J,
KEY_EN_K,
KEY_EN_L,
KEY_EN_SEMICOLON,
KEY_EN_QUOTE,
KEY_EN_UNUSED,
KEY_EN_ANSI_ENTER,
// Fourth row
KEY_EN_LEFT_SHIFT,
KEY_EN_UNUSED,
KEY_EN_Z,
KEY_EN_X,
KEY_EN_C,
KEY_EN_V,
KEY_EN_B,
KEY_EN_N,
KEY_EN_M,
KEY_EN_COMMA,
KEY_EN_PERIOD,
KEY_EN_FORWARD_SLASH,
KEY_EN_UNUSED,
KEY_EN_RIGHT_SHIFT,
// Fifth row
KEY_EN_LEFT_CONTROL,
KEY_EN_LEFT_WINDOWS,
KEY_EN_LEFT_ALT,
"Left Space",
KEY_EN_SPACE,
"Right Space",
KEY_EN_RIGHT_ALT,
KEY_EN_MENU,
KEY_EN_RIGHT_CONTROL,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_RIGHT_FUNCTION
};
static const char *led_names_65[] =
{
KEY_EN_UNUSED,
KEY_EN_ESCAPE,
KEY_EN_1,
KEY_EN_2,
KEY_EN_3,
KEY_EN_4,
KEY_EN_5,
KEY_EN_6,
KEY_EN_7,
KEY_EN_8,
KEY_EN_9,
KEY_EN_0,
KEY_EN_MINUS,
KEY_EN_EQUALS,
KEY_EN_UNUSED,
KEY_EN_BACKSPACE,
KEY_EN_TAB,
KEY_EN_Q,
KEY_EN_W,
KEY_EN_E,
KEY_EN_R,
KEY_EN_T,
KEY_EN_Y,
KEY_EN_U,
KEY_EN_I,
KEY_EN_O,
KEY_EN_P,
KEY_EN_LEFT_BRACKET,
KEY_EN_RIGHT_BRACKET,
KEY_EN_ANSI_BACK_SLASH,
KEY_EN_CAPS_LOCK,
KEY_EN_A,
KEY_EN_S,
KEY_EN_D,
KEY_EN_F,
KEY_EN_G,
KEY_EN_H,
KEY_EN_J,
KEY_EN_K,
KEY_EN_L,
KEY_EN_SEMICOLON,
KEY_EN_QUOTE,
KEY_EN_UNUSED,
KEY_EN_ANSI_ENTER,
KEY_EN_LEFT_SHIFT,
KEY_EN_UNUSED,
KEY_EN_Z,
KEY_EN_X,
KEY_EN_C,
KEY_EN_V,
KEY_EN_B,
KEY_EN_N,
KEY_EN_M,
KEY_EN_COMMA,
KEY_EN_PERIOD,
KEY_EN_FORWARD_SLASH,
KEY_EN_UNUSED,
KEY_EN_RIGHT_SHIFT,
KEY_EN_LEFT_CONTROL,
KEY_EN_LEFT_WINDOWS,
KEY_EN_LEFT_ALT,
"Left Space",
KEY_EN_SPACE,
"Right Space",
KEY_EN_RIGHT_ALT,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_UNUSED,
KEY_EN_RIGHT_FUNCTION,
KEY_EN_HOME,
KEY_EN_DELETE,
KEY_EN_PAGE_UP,
KEY_EN_PAGE_DOWN,
KEY_EN_UP_ARROW,
KEY_EN_LEFT_ARROW,
KEY_EN_DOWN_ARROW,
KEY_EN_RIGHT_ARROW
};
/**------------------------------------------------------------------*\
@name HyperX Alloy Origins 60 and 65
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXAlloyOrigins60and65
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXAlloyOrigins60and65::RGBController_HyperXAlloyOrigins60and65(HyperXAlloyOrigins60and65Controller* controller_ptr, AlloyOrigins60and65MappingLayoutType keyboard_layout)
{
controller = controller_ptr;
layout = keyboard_layout;
switch(layout)
{
case ALLOY_ORIGINS_60_LAYOUT:
description = "HyperX Alloy Origins 60 Keyboard Device";
break;
case ALLOY_ORIGINS_65_LAYOUT:
description = "HyperX Alloy Origins 65 Keyboard Device";
break;
}
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXAlloyOrigins60and65::KeepaliveThread, this);
}
RGBController_HyperXAlloyOrigins60and65::~RGBController_HyperXAlloyOrigins60and65()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXAlloyOrigins60and65::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
std::vector<led_zone> led_zones;
const char* const *led_names;
switch(layout)
{
case ALLOY_ORIGINS_60_LAYOUT:
default:
led_names = led_names_60;
led_zones.push_back({ZONE_EN_KEYBOARD, ZONE_TYPE_MATRIX, 71, new matrix_map_type{5, 14, (unsigned int *)&matrix_map_60}});
break;
case ALLOY_ORIGINS_65_LAYOUT:
led_names = led_names_65;
led_zones.push_back({ZONE_EN_KEYBOARD, ZONE_TYPE_MATRIX, 77, new matrix_map_type{5, 15, (unsigned int *)&matrix_map_65}});
break;
}
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
zone new_zone;
new_zone.name = led_zones[zone_idx].name;
new_zone.type = led_zones[zone_idx].type;
new_zone.leds_min = led_zones[zone_idx].size;
new_zone.leds_max = led_zones[zone_idx].size;
new_zone.leds_count = led_zones[zone_idx].size;
if(led_zones[zone_idx].type == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = led_zones[zone_idx].matrix;
}
else
{
new_zone.matrix_map = NULL;
}
zones.push_back(new_zone);
total_led_count += led_zones[zone_idx].size;
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXAlloyOrigins60and65::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXAlloyOrigins60and65::DeviceUpdateLEDs()
{
controller->SetLEDsDirect(colors);
}
void RGBController_HyperXAlloyOrigins60and65::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyOrigins60and65::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyOrigins60and65::DeviceUpdateMode()
{
}
void RGBController_HyperXAlloyOrigins60and65::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);;
}
}
@@ -0,0 +1,57 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyOrigins60and65.h |
| |
| RGBController for HyperX Alloy Origins 60 and 65 |
| keyboard |
| |
| Derek Huber 18 Mar 2023 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXAlloyOrigins60and65Controller.h"
enum AlloyOrigins60and65MappingLayoutType
{
ALLOY_ORIGINS_60_LAYOUT,
ALLOY_ORIGINS_65_LAYOUT
};
typedef struct
{
const char* name;
const zone_type type;
const unsigned int size;
matrix_map_type* matrix;
} led_zone;
class RGBController_HyperXAlloyOrigins60and65 : public RGBController
{
public:
RGBController_HyperXAlloyOrigins60and65(HyperXAlloyOrigins60and65Controller* controller_ptr, AlloyOrigins60and65MappingLayoutType keyboard_layout);
~RGBController_HyperXAlloyOrigins60and65();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXAlloyOrigins60and65Controller* controller;
AlloyOrigins60and65MappingLayoutType layout;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -0,0 +1,159 @@
/*---------------------------------------------------------*\
| HyperXAlloyOriginsController.cpp |
| |
| Driver for HyperX Alloy Origins keyboard |
| |
| Adam Honse (CalcProgrammer1) 11 Jul 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXAlloyOriginsController.h"
#include "StringUtils.h"
// Skip these indices in the color output
static unsigned int skip_idx[] = { 23, 29, 41, 47, 59, 70, 71, 87, 88, 93, 99, 100, 102, 108, 113, 114, 120, 123, 124 };
HyperXAlloyOriginsController::HyperXAlloyOriginsController(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXAlloyOriginsController::~HyperXAlloyOriginsController()
{
hid_close(dev);
}
std::string HyperXAlloyOriginsController::GetDeviceLocation()
{
return("HID " + location);
}
std::string HyperXAlloyOriginsController::GetNameString()
{
return(name);
}
std::string HyperXAlloyOriginsController::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXAlloyOriginsController::SetLEDsDirect(std::vector<RGBColor> colors)
{
/*-----------------------------------------------------*\
| Insert color data for unused positions |
\*-----------------------------------------------------*/
for(unsigned int skip_cnt = 0; skip_cnt < (sizeof(skip_idx) / sizeof(skip_idx[0])); skip_cnt++)
{
colors.insert(colors.begin() + skip_idx[skip_cnt], 0x00000000);
}
/*-----------------------------------------------------*\
| Set up variables to track progress of color transmit |
| Do this after inserting blanks |
\*-----------------------------------------------------*/
int colors_to_send = (int)colors.size();
int colors_sent = 0;
SendDirectInitialization();
for(int pkt_idx = 0; pkt_idx < 9; pkt_idx++)
{
if(colors_to_send > 16)
{
SendDirectColorPacket(&colors[colors_sent], 16);
colors_sent += 16;
colors_to_send -= 16;
}
else if(colors_to_send > 0)
{
SendDirectColorPacket(&colors[colors_sent], colors_to_send);
colors_sent += colors_to_send;
colors_to_send -= colors_to_send;
}
else
{
RGBColor temp = 0x00000000;
SendDirectColorPacket(&temp, 1);
}
}
}
void HyperXAlloyOriginsController::SendDirectInitialization()
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x00;
buf[0x01] = 0x04;
buf[0x02] = 0xF2;
buf[0x09] = 0x09;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 65);
}
void HyperXAlloyOriginsController::SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count
)
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x00;
/*-----------------------------------------------------*\
| The maximum number of colors per packet is 16 |
\*-----------------------------------------------------*/
if(color_count > 16)
{
color_count = 16;
}
/*-----------------------------------------------------*\
| Copy in color data |
\*-----------------------------------------------------*/
for(unsigned int color_idx = 0; color_idx < color_count; color_idx++)
{
buf[(color_idx * 4) + 1] = 0x81;
buf[(color_idx * 4) + 2] = RGBGetRValue(color_data[color_idx]);
buf[(color_idx * 4) + 3] = RGBGetGValue(color_data[color_idx]);
buf[(color_idx * 4) + 4] = RGBGetBValue(color_data[color_idx]);
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, buf, 65);
}
@@ -0,0 +1,41 @@
/*---------------------------------------------------------*\
| HyperXAlloyOriginsController.h |
| |
| Driver for HyperX Alloy Origins keyboard |
| |
| Adam Honse (CalcProgrammer1) 11 Jul 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
class HyperXAlloyOriginsController
{
public:
HyperXAlloyOriginsController(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXAlloyOriginsController();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirectInitialization();
void SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count
);
};
@@ -0,0 +1,316 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyOrigins.cpp |
| |
| RGBController for HyperX Alloy Origins keyboard |
| |
| Adam Honse (CalcProgrammer1) 11 Jul 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXAlloyOrigins.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[6][23] =
{ { 0, NA, 12, 18, 23, 28, NA, 34, 39, 44, 50, NA, 55, 61, 65, 71, 77, 81, 86, NA, NA, NA, NA },
{ 1, 7, 13, 19, 24, 29, 35, 40, 45, 51, 56, NA, 62, 66, 71, 72, 78, 82, 87, 90, 95, 99, 104 },
{ 2, NA, 8, 14, 20, 25, NA, 30, 36, 41, 46, 52, 57, 63, 67, 73, 79, 83, 88, 91, 96, 100, 105 },
{ 3, NA, 9, 15, 21, 26, NA, 31, 37, 42, 47, 53, 58, 64, 68, 74, NA, NA, NA, 92, 97, 101, NA },
{ 4, 6, 10, 16, 22, 27, NA, 32, NA, 38, 43, 48, 54, 59, 69, 75, NA, 84, NA, 93, 98, 102, 106 },
{ 5, 11, 17, NA, NA, NA, NA, 33, NA, NA, NA, NA, 49, 60, 70, 76, 80, 85, 89, 94, NA, 103, NA } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const unsigned int zone_sizes[] =
{
107,
};
static const char *led_names[] =
{
KEY_EN_ESCAPE,
KEY_EN_BACK_TICK,
KEY_EN_TAB,
KEY_EN_CAPS_LOCK,
KEY_EN_LEFT_SHIFT,
KEY_EN_LEFT_CONTROL,
KEY_EN_ISO_BACK_SLASH,
KEY_EN_1,
KEY_EN_Q,
KEY_EN_A,
KEY_EN_Z,
KEY_EN_LEFT_WINDOWS,
KEY_EN_F1,
KEY_EN_2,
KEY_EN_W,
KEY_EN_S,
KEY_EN_X,
KEY_EN_LEFT_ALT,
KEY_EN_F2,
KEY_EN_3,
KEY_EN_E,
KEY_EN_D,
KEY_EN_C,
// Skip index 23
KEY_EN_F3,
KEY_EN_4,
KEY_EN_R,
KEY_EN_F,
KEY_EN_V,
// Skip index 29
KEY_EN_F4,
KEY_EN_5,
KEY_EN_T,
KEY_EN_G,
KEY_EN_B,
KEY_EN_SPACE,
KEY_EN_F5,
KEY_EN_6,
KEY_EN_Y,
KEY_EN_H,
KEY_EN_N,
// Skip index 41
KEY_EN_F6,
KEY_EN_7,
KEY_EN_U,
KEY_EN_J,
KEY_EN_M,
// Skip index 47
KEY_EN_F7,
KEY_EN_8,
KEY_EN_I,
KEY_EN_K,
KEY_EN_COMMA,
KEY_EN_RIGHT_ALT,
KEY_EN_F8,
KEY_EN_9,
KEY_EN_O,
KEY_EN_L,
KEY_EN_PERIOD,
// Skip index 59
KEY_EN_F9,
KEY_EN_0,
KEY_EN_P,
KEY_EN_SEMICOLON,
KEY_EN_FORWARD_SLASH,
KEY_EN_RIGHT_FUNCTION,
KEY_EN_F10,
KEY_EN_MINUS,
KEY_EN_LEFT_BRACKET,
KEY_EN_QUOTE,
// Skip index 70
// Skip index 71
KEY_EN_F11,
KEY_EN_EQUALS,
KEY_EN_RIGHT_BRACKET,
KEY_EN_POUND,
"Key: / (ABNT)",
KEY_EN_MENU,
KEY_EN_F12,
KEY_EN_BACKSPACE,
KEY_EN_ANSI_BACK_SLASH,
KEY_EN_ANSI_ENTER,
KEY_EN_RIGHT_SHIFT,
KEY_EN_RIGHT_CONTROL,
KEY_EN_PRINT_SCREEN,
KEY_EN_INSERT,
KEY_EN_DELETE,
// Skip index 87
// Skip index 88
KEY_EN_LEFT_ARROW,
KEY_EN_SCROLL_LOCK,
KEY_EN_HOME,
KEY_EN_END,
// Skip index 93
KEY_EN_UP_ARROW,
KEY_EN_DOWN_ARROW,
KEY_EN_PAUSE_BREAK,
KEY_EN_PAGE_UP,
KEY_EN_PAGE_DOWN,
// Skip index 99
// Skip index 100
KEY_EN_RIGHT_ARROW,
// Skip index 102
KEY_EN_NUMPAD_LOCK,
KEY_EN_NUMPAD_7,
KEY_EN_NUMPAD_4,
KEY_EN_NUMPAD_1,
KEY_EN_NUMPAD_0,
// Skip index 108
KEY_EN_NUMPAD_DIVIDE,
KEY_EN_NUMPAD_8,
KEY_EN_NUMPAD_5,
KEY_EN_NUMPAD_2,
// Skip index 113
// Skip index 114
KEY_EN_NUMPAD_TIMES,
KEY_EN_NUMPAD_9,
KEY_EN_NUMPAD_6,
KEY_EN_NUMPAD_3,
KEY_EN_NUMPAD_PERIOD,
// Skip index 120
KEY_EN_NUMPAD_MINUS,
KEY_EN_NUMPAD_PLUS,
// Skip index 123
// Skip index 124
KEY_EN_NUMPAD_ENTER,
};
/**------------------------------------------------------------------*\
@name HyperX Alloy Origins
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXAlloyOrigins
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXAlloyOrigins::RGBController_HyperXAlloyOrigins(HyperXAlloyOriginsController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
description = "HyperX Alloy Origins Keyboard Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
/*-----------------------------------------------------*\
| The Corsair Lighting Node Pro requires a packet within|
| 20 seconds of sending the lighting change in order |
| to not revert back into rainbow mode. Start a thread |
| to continuously send a keepalive packet every 5s |
\*-----------------------------------------------------*/
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXAlloyOrigins::KeepaliveThread, this);
}
RGBController_HyperXAlloyOrigins::~RGBController_HyperXAlloyOrigins()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXAlloyOrigins::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
zone new_zone;
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
new_zone.leds_min = zone_sizes[zone_idx];
new_zone.leds_max = zone_sizes[zone_idx];
new_zone.leds_count = zone_sizes[zone_idx];
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = new matrix_map_type;
new_zone.matrix_map->height = 6;
new_zone.matrix_map->width = 23;
new_zone.matrix_map->map = (unsigned int *)&matrix_map;
}
else
{
new_zone.matrix_map = NULL;
}
zones.push_back(new_zone);
total_led_count += zone_sizes[zone_idx];
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXAlloyOrigins::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXAlloyOrigins::DeviceUpdateLEDs()
{
controller->SetLEDsDirect(colors);
}
void RGBController_HyperXAlloyOrigins::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyOrigins::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyOrigins::DeviceUpdateMode()
{
}
void RGBController_HyperXAlloyOrigins::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);;
}
}
@@ -0,0 +1,41 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyOrigins.h |
| |
| RGBController for HyperX Alloy Origins keyboard |
| |
| Adam Honse (CalcProgrammer1) 11 Jul 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXAlloyOriginsController.h"
class RGBController_HyperXAlloyOrigins : public RGBController
{
public:
RGBController_HyperXAlloyOrigins(HyperXAlloyOriginsController* controller_ptr);
~RGBController_HyperXAlloyOrigins();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXAlloyOriginsController* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -0,0 +1,191 @@
/*---------------------------------------------------------*\
| HyperXAlloyOriginsCoreController.cpp |
| |
| Driver for HyperX Alloy Origins Core keyboard |
| |
| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 |
| Mike White (kamaaina) 09 Jun 2021 |
| carlos jordao 15 Mar 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXAlloyOriginsCoreController.h"
#include "StringUtils.h"
#include "LogManager.h"
HyperXAlloyOriginsCoreController::HyperXAlloyOriginsCoreController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name)
{
dev = dev_handle;
location = dev_info->path;
name = dev_name;
/*-----------------------------------------------------*\
| Get the firmware version from the device info |
\*-----------------------------------------------------*/
char fw_version_buf[8];
memset(fw_version_buf, '\0', sizeof(fw_version_buf));
unsigned short version = dev_info->release_number;
snprintf(fw_version_buf, 8, "%.2X.%.2X", (version & 0xFF00) >> 8, version & 0x00FF);
firmware_version = fw_version_buf;
}
HyperXAlloyOriginsCoreController::~HyperXAlloyOriginsCoreController()
{
hid_close(dev);
}
std::string HyperXAlloyOriginsCoreController::GetDeviceLocation()
{
return("HID " + location);
}
std::string HyperXAlloyOriginsCoreController::GetNameString()
{
return(name);
}
std::string HyperXAlloyOriginsCoreController::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
std::string HyperXAlloyOriginsCoreController::GetFirmwareVersion()
{
return(firmware_version);
}
unsigned int HyperXAlloyOriginsCoreController::GetVariant()
{
unsigned char packet[65];
unsigned int variant = 0;
int actual = 0;
memset(packet, 0x00, sizeof(packet));
/*---------------------------------------*\
| Command 10 asks some data from keyboard |
| The answer looks like: |
| * command answer header (bytes 0-4) |
| * data length: byte 4 |
| * version (bytes 5-6) |
| * Product string (bytes 9-33) |
| * Layout variant (byte 56) |
\*---------------------------------------*/
packet[1] = 0x10;
hid_write(dev, packet, 65);
memset(packet, 0x00, sizeof(packet));
actual = hid_read(dev, packet, 65);
if(actual > 0)
variant = packet[56];
else
variant = 0;
LOG_DEBUG("[HyperX Alloy Origins Core] variant: 0x%02X", variant);
return variant;
}
void HyperXAlloyOriginsCoreController::SetBrightness(unsigned int brightness)
{
unsigned char packet[65];
memset(packet, 0x00, sizeof(packet));
packet[1] = 0xA7;
packet[4] = 0x01;
packet[5] = brightness;
hid_write(dev, packet, 65);
}
void HyperXAlloyOriginsCoreController::SetLEDsDirect(std::vector<led> leds, std::vector<RGBColor> colors)
{
/*------------------------------------------------------------------------------*\
| * Always send 380 bytes to the keyboard and a total of 94 led indexes. |
| The colors are grouped into segments of 48 bytes. |
| Each one is divided into: |
| 6 Green + 2 zeroes + 6 Green + 2 zeroes + |
| 6 Red + 2 zeroes + 6 Red + 2 zeroes + |
| 6 Blue + 2 zeroes + 6 Blue + 2 zeroes |
| \=---> sector 0 \=--> sector 1 |
| Every 6 colors form a sector. The names are arbitrary, just to make clear how |
| to set the colors into the buffer. |
| So each segment has 2 sectors and 12 colors. |
| The last 10 colors don't fill completely the last segment. |
| * All 94 colors can be sent even if some of them aren't used by the physical |
| keyboard. This allows to lit every key, even if not mapped directly. |
\*------------------------------------------------------------------------------*/
unsigned int segment = 0, sector = 0, sequence = 0;
unsigned int total_colors = 0;
memset(color_buf, 0x00, sizeof(color_buf));
/*---------------------------------------------------------------------------*\
| transfer the colors to the buffer. Max 94 colors to avoid buffer overflow. |
\*---------------------------------------------------------------------------*/
if(colors.size() > 94)
{
total_colors = 94;
}
else
{
total_colors = (unsigned int)colors.size();
}
unsigned int pos = 0, color_idx = 0;
for(unsigned int i = 0; i < total_colors; i++)
{
color_idx = leds[i].value;
segment = (color_idx / 12) * 48;
sector = ((color_idx / 6) & 1) * 8;
sequence = color_idx % 6;
pos = segment + sector + sequence;
color_buf[pos ] = RGBGetGValue(colors[i]);
color_buf[pos + 16] = RGBGetRValue(colors[i]);
color_buf[pos + 32] = RGBGetBValue(colors[i]);
}
}
void HyperXAlloyOriginsCoreController::SendRGBToDevice()
{
unsigned int sentBytes = 0;
unsigned int bytesToSend = sizeof(color_buf);
unsigned int payloadSize = 60;
unsigned int seq = 0;
while(sentBytes < bytesToSend)
{
if (bytesToSend - sentBytes < payloadSize)
{
payloadSize = bytesToSend - sentBytes;
}
unsigned char packet[65];
memset(packet, 0x00, sizeof(packet));
packet[1] = 0xA2;
packet[2] = seq++;
packet[4] = payloadSize;
memcpy(&packet[5], &color_buf[sentBytes], payloadSize);
hid_write(dev, packet, payloadSize + 5);
sentBytes += payloadSize;
}
}
@@ -0,0 +1,43 @@
/*---------------------------------------------------------*\
| HyperXAlloyOriginsCoreController.h |
| |
| Driver for HyperX Alloy Origins Core keyboard |
| |
| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
#define HYPERX_ALLOY_ORIGINS_CORE_ANSI 0x09
#define HYPERX_ALLOY_ORIGINS_CORE_ABNT2 0x10
class HyperXAlloyOriginsCoreController
{
public:
HyperXAlloyOriginsCoreController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name);
~HyperXAlloyOriginsCoreController();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
std::string GetFirmwareVersion();
unsigned int GetVariant();
void SetLEDsDirect(std::vector<led> leds, std::vector<RGBColor> colors);
void SendRGBToDevice();
void SetBrightness(unsigned int brightness);
private:
hid_device* dev;
std::string location;
std::string firmware_version;
std::string name;
unsigned char color_buf[380];
};
@@ -0,0 +1,253 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyOriginsCore.cpp |
| |
| RGBController for HyperX Alloy Origins Core keyboard |
| |
| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 |
| carlos jordao 15 Mar 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXAlloyOriginsCore.h"
#include "KeyboardLayoutManager.h"
using namespace std::chrono_literals;
#define HYPERX_MIN_BRIGHTNESS 0
#define HYPERX_MAX_BRIGHTNESS 255
#define NA 0xFFFFFFFF
/*----------------------------------*\
| Maps LED position number to keys |
| * based on ANSI QWERTY |
\*----------------------------------*/
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
/*--------------------------------------------------------------------------------*\
| This keyboard (TKL) always receives 94 led colors. |
| * Some indexes are just blank (unused). |
| * Regional layouts have a few different enabled or disabled led indexes. |
| * Below there is the association of the led indexes and the keyboard keys for |
| DEFAULT layout. |
\*--------------------------------------------------------------------------------*/
std::vector<unsigned int> hyperx_core_default_values
{
0, 1, 2, 3, 4, 5, 6, 7, 48, 49, 50, 51, 52, 53, 54, 55,
8, 9, 10, 11, 12, 13, 14, 15, 16, 56, 57, 58, 59, 60, 61, 62, 63,
17, 18, 19, 20, 21, 22, 23, 24, 64, 65, 66, 67, 68, 69, 70, 71, 72,
25, 26, 27, 28, 29, 30, 31, 32, 73, 74, 75, 76, 77, 78,
33, 34, 35, 36, 37, 38, 39, 40, 79, 80, 81, 82, 84, 85,
41, 42, 43, 45, 86, 87, 88, 89, 90, 91, 92,
};
layout_values hyperx_core_layout
{
hyperx_core_default_values,
{
},
};
/*--------------------------------------------*\
| Provide values to keys that has been changed |
| in DEFAULT layout. |
\*--------------------------------------------*/
std::map<KEYBOARD_LAYOUT, key_set> regional_overlay_abnt2
{
{
KEYBOARD_LAYOUT_ABNT2,
{
/*-------------------------------------------------------------------------------------------------------------------------------------*\
| Edit Keys |
| Zone, Row, Column, Value, Key, Alternate Name, OpCode, |
\*-------------------------------------------------------------------------------------------------------------------------------------*/
{ 0, 4, 11, 82, KEY_EN_SEMICOLON, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, },
{ 0, 4, 12, 83, KEY_EN_FORWARD_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, },
},
}
};
/**------------------------------------------------------------------*\
@name HyperX Alloy Origins Core
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXAlloyOriginsCore
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXAlloyOriginsCore::RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
description = "HyperX Alloy Origins Core Keyboard Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
version = controller->GetFirmwareVersion();
variant = controller->GetVariant();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Direct.brightness_min = HYPERX_MIN_BRIGHTNESS;
Direct.brightness_max = HYPERX_MAX_BRIGHTNESS;
Direct.brightness = HYPERX_MAX_BRIGHTNESS;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
/*-----------------------------------------------------*\
| The HyperX Origins Core requires a packet within few |
| seconds of sending the lighting change in order to |
| not revert back into current profile. Start a thread |
| to continuously send color values each 10ms |
\*-----------------------------------------------------*/
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXAlloyOriginsCore::KeepaliveThread, this);
}
RGBController_HyperXAlloyOriginsCore::~RGBController_HyperXAlloyOriginsCore()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXAlloyOriginsCore::SetupZones()
{
unsigned int total_leds = 0;
zone new_zone;
KEYBOARD_LAYOUT layout_name;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
/*-----------------------------------------------------*\
| Regional configuration |
| * variant is extracted from keyboard info |
\*-----------------------------------------------------*/
switch(variant)
{
case HYPERX_ALLOY_ORIGINS_CORE_ABNT2:
layout_name = KEYBOARD_LAYOUT_ABNT2;
hyperx_core_layout.regional_overlay = regional_overlay_abnt2;
break;
case HYPERX_ALLOY_ORIGINS_CORE_ANSI:
default:
layout_name = KEYBOARD_LAYOUT_ANSI_QWERTY;
break;
}
KeyboardLayoutManager new_kb(layout_name, KEYBOARD_SIZE_TKL, hyperx_core_layout);
total_leds = new_kb.GetKeyCount();
matrix_map_type * keyboard_map = new matrix_map_type;
new_zone.leds_count = total_leds;
new_zone.leds_min = new_zone.leds_count;
new_zone.leds_max = new_zone.leds_count;
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = keyboard_map;
keyboard_map->height = new_kb.GetRowCount();
keyboard_map->width = new_kb.GetColumnCount();
keyboard_map->map = new unsigned int[keyboard_map->height * keyboard_map->width];
new_kb.GetKeyMap(keyboard_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT);
}
else
{
new_zone.matrix_map = NULL;
}
zones.push_back(new_zone);
for(unsigned int led_idx = 0; led_idx < total_leds; led_idx++)
{
led new_led;
new_led.name = new_kb.GetKeyAltNameAt(led_idx);
if(new_led.name == KEY_EN_UNUSED)
new_led.name = new_kb.GetKeyNameAt(led_idx);
new_led.value = new_kb.GetKeyValueAt(led_idx);
leds.push_back(new_led);
}
}
SetupColors();
}
void RGBController_HyperXAlloyOriginsCore::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXAlloyOriginsCore::DeviceUpdateLEDs()
{
controller->SetLEDsDirect(leds, colors);
}
void RGBController_HyperXAlloyOriginsCore::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyOriginsCore::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXAlloyOriginsCore::DeviceUpdateMode()
{
controller->SetBrightness(modes[active_mode].brightness);
}
void RGBController_HyperXAlloyOriginsCore::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
controller->SendRGBToDevice();
}
}
std::this_thread::sleep_for(10ms);
}
}
@@ -0,0 +1,45 @@
/*---------------------------------------------------------*\
| RGBController_HyperXAlloyOriginsCore.h |
| |
| RGBController for HyperX Alloy Origins Core keyboard |
| |
| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXAlloyOriginsCoreController.h"
#define HYPERX_ALLOY_ORIGINS_CORE_ANSI 0x09
#define HYPERX_ALLOY_ORIGINS_CORE_ABNT2 0x10
class RGBController_HyperXAlloyOriginsCore : public RGBController
{
public:
RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* controller_ptr);
~RGBController_HyperXAlloyOriginsCore();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXAlloyOriginsCoreController* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
unsigned int variant;
};
@@ -0,0 +1,121 @@
/*---------------------------------------------------------*\
| HyperXEve1800Controller.cpp |
| |
| Driver for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXEve1800Controller.h"
#include "StringUtils.h"
HyperXEve1800Controller::HyperXEve1800Controller(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXEve1800Controller::~HyperXEve1800Controller()
{
hid_close(dev);
}
std::string HyperXEve1800Controller::GetDeviceLocation()
{
return("HID: " + location);
}
std::string HyperXEve1800Controller::GetNameString()
{
return(name);
}
std::string HyperXEve1800Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXEve1800Controller::SetBrightness(unsigned int brightness)
{
unsigned char buf[65];
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x40;
buf[0x01] = 0x01;
buf[0x02] = 0x00;
buf[0x03] = 0x00;
buf[0x04] = brightness & 0xFF;
hid_write(dev, buf, 65);
}
void HyperXEve1800Controller::SetLEDsDirect(std::vector<RGBColor> colors)
{
SendDirectInitialization();
if(colors.empty())
{
RGBColor temp = 0x00000000;
SendDirectColorPacket(&temp, 1);
}
else
{
SendDirectColorPacket(&colors[0], (unsigned int)colors.size());
}
}
void HyperXEve1800Controller::SendDirectInitialization()
{
unsigned char buf[65];
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x44;
buf[0x01] = 0x01;
buf[0x02] = 0x04;
buf[0x03] = 0x00;
hid_write(dev, buf, 65);
}
void HyperXEve1800Controller::SendDirectColorPacket(RGBColor* color_data, unsigned int color_count)
{
unsigned char buf[65];
memset(buf, 0x00, sizeof(buf));
buf[0x00] = 0x44;
buf[0x01] = 0x02;
buf[0x02] = 0x00;
buf[0x03] = 0x00;
/*-----------------------------------------------------*\
| The Eve 1800 exposes 10 lighting zones, but this |
| report format can carry up to 20 RGB triplets. |
\*-----------------------------------------------------*/
if(color_count > 20)
{
color_count = 20;
}
for(unsigned int color_idx = 0; color_idx < color_count; color_idx++)
{
buf[4 + (color_idx * 3)] = RGBGetRValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 1] = RGBGetGValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 2] = RGBGetBValue(color_data[color_idx]);
}
hid_write(dev, buf, 65);
}
@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| HyperXEve1800Controller.h |
| |
| Driver for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
class HyperXEve1800Controller
{
public:
HyperXEve1800Controller(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXEve1800Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetBrightness(unsigned int brightness);
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirectInitialization();
void SendDirectColorPacket(RGBColor* color_data, unsigned int color_count);
};
@@ -0,0 +1,127 @@
/*---------------------------------------------------------*\
| RGBController_HyperXEve1800.cpp |
| |
| RGBController for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_HyperXEve1800.h"
using namespace std::chrono_literals;
#define HYPERX_EVE_1800_BRIGHTNESS_MIN 0x00
#define HYPERX_EVE_1800_BRIGHTNESS_MAX 0xFF
#define HYPERX_EVE_1800_ZONE_COUNT 10
/**------------------------------------------------------------------*\
@name HyperX Eve 1800
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXEve1800
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXEve1800::RGBController_HyperXEve1800(HyperXEve1800Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
description = "HyperX Eve 1800 Keyboard Device";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
Direct.brightness_min = HYPERX_EVE_1800_BRIGHTNESS_MIN;
Direct.brightness_max = HYPERX_EVE_1800_BRIGHTNESS_MAX;
Direct.brightness = HYPERX_EVE_1800_BRIGHTNESS_MAX;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXEve1800::KeepaliveThread, this);
}
RGBController_HyperXEve1800::~RGBController_HyperXEve1800()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
delete controller;
}
void RGBController_HyperXEve1800::SetupZones()
{
zone new_zone;
new_zone.name = "Keyboard";
new_zone.type = ZONE_TYPE_LINEAR;
new_zone.leds_min = HYPERX_EVE_1800_ZONE_COUNT;
new_zone.leds_max = HYPERX_EVE_1800_ZONE_COUNT;
new_zone.leds_count = HYPERX_EVE_1800_ZONE_COUNT;
new_zone.matrix_map = NULL;
zones.push_back(new_zone);
for(unsigned int led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
{
led new_led;
new_led.name = "Zone ";
new_led.name.append(std::to_string(led_idx + 1));
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXEve1800::ResizeZone(int /*zone*/, int /*new_size*/)
{
}
void RGBController_HyperXEve1800::DeviceUpdateLEDs()
{
controller->SetLEDsDirect(colors);
last_update_time = std::chrono::steady_clock::now();
}
void RGBController_HyperXEve1800::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXEve1800::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXEve1800::DeviceUpdateMode()
{
controller->SetBrightness(modes[active_mode].brightness);
DeviceUpdateLEDs();
}
void RGBController_HyperXEve1800::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);
}
}
@@ -0,0 +1,39 @@
/*---------------------------------------------------------*\
| RGBController_HyperXEve1800.h |
| |
| RGBController for HyperX Eve 1800 keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXEve1800Controller.h"
class RGBController_HyperXEve1800 : public RGBController
{
public:
RGBController_HyperXEve1800(HyperXEve1800Controller* controller_ptr);
~RGBController_HyperXEve1800();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXEve1800Controller* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};
@@ -0,0 +1,202 @@
/*---------------------------------------------------------*\
| HyperXKeyboardControllerDetect.cpp |
| |
| Driver for HyperX keyboards |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include "Detector.h"
#include "HyperXAlloyEliteController.h"
#include "HyperXAlloyElite2Controller.h"
#include "HyperXAlloyFPSController.h"
#include "HyperXAlloyOriginsController.h"
#include "HyperXAlloyOriginsCoreController.h"
#include "HyperXAlloyOrigins60and65Controller.h"
#include "HyperXEve1800Controller.h"
#include "HyperXOrigins2_65Controller.h"
#include "RGBController_HyperXAlloyElite.h"
#include "RGBController_HyperXAlloyElite2.h"
#include "RGBController_HyperXAlloyFPS.h"
#include "RGBController_HyperXAlloyOrigins.h"
#include "RGBController_HyperXAlloyOriginsCore.h"
#include "RGBController_HyperXAlloyOrigins60and65.h"
#include "RGBController_HyperXEve1800.h"
#include "RGBController_HyperXOrigins2_65.h"
/*-----------------------------------------------------*\
| HyperX keyboard vendor and product IDs |
\*-----------------------------------------------------*/
#define HYPERX_KEYBOARD_VID 0x0951
#define HYPERX_ALLOY_ELITE_PID 0x16BE
#define HYPERX_ALLOY_ELITE_2_PID 0x1711
#define HYPERX_ALLOY_FPS_RGB_PID 0x16DC
#define HYPERX_ALLOY_ORIGINS_PID 0x16E5
#define HYPERX_ALLOY_ORIGINS_CORE_PID 0x16E6
#define HYPERX_ALLOY_ORIGINS_60_PID 0x1734
/*-----------------------------------------------------*\
| HyperX keyboard vendor and product IDs (HP) |
\*-----------------------------------------------------*/
#define HP_KEYBOARD_VID 0x03F0
#define HYPERX_ALLOY_ELITE_2_HP_PID 0x058F
#define HYPERX_ALLOY_ORIGINS_60_HP_PID 0x0C8E
#define HYPERX_ALLOY_ORIGINS_65_HP_PID 0x038F
#define HYPERX_ALLOY_ORIGINS_CORE_HP_PID 0x098F
#define HYPERX_ALLOY_ORIGINS_HP_PID 0x0591
#define HYPERX_EVE_1800_HP_PID 0x08C2
#define HYPERX_ORIGINS_2_65_HP_PID 0x0CC2
AlloyOrigins60and65MappingLayoutType GetAlloyOrigins60and65MappingLayoutType(int pid)
{
switch(pid)
{
case HYPERX_ALLOY_ORIGINS_60_PID:
case HYPERX_ALLOY_ORIGINS_60_HP_PID:
return ALLOY_ORIGINS_60_LAYOUT;
case HYPERX_ALLOY_ORIGINS_65_HP_PID:
return ALLOY_ORIGINS_65_LAYOUT;
default:
return ALLOY_ORIGINS_60_LAYOUT;
}
}
void DetectHyperXAlloyElite(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXAlloyEliteController* controller = new HyperXAlloyEliteController(dev, info->path, name);
RGBController_HyperXAlloyElite* rgb_controller = new RGBController_HyperXAlloyElite(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXAlloyElite2(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXAlloyElite2Controller* controller = new HyperXAlloyElite2Controller(dev, info->path, name);
RGBController_HyperXAlloyElite2* rgb_controller = new RGBController_HyperXAlloyElite2(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXAlloyFPS(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXAlloyFPSController* controller = new HyperXAlloyFPSController(dev, info->path, name);
RGBController_HyperXAlloyFPS* rgb_controller = new RGBController_HyperXAlloyFPS(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXAlloyOrigins(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXAlloyOriginsController* controller = new HyperXAlloyOriginsController(dev, info->path, name);
RGBController_HyperXAlloyOrigins* rgb_controller = new RGBController_HyperXAlloyOrigins(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXAlloyOriginsCore(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXAlloyOriginsCoreController* controller = new HyperXAlloyOriginsCoreController(dev, info, name);
RGBController_HyperXAlloyOriginsCore* rgb_controller = new RGBController_HyperXAlloyOriginsCore(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXAlloyOrigins60and65(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXAlloyOrigins60and65Controller* controller = new HyperXAlloyOrigins60and65Controller(dev, info->path, name);
AlloyOrigins60and65MappingLayoutType layout = GetAlloyOrigins60and65MappingLayoutType(info->product_id);
RGBController_HyperXAlloyOrigins60and65* rgb_controller = new RGBController_HyperXAlloyOrigins60and65(controller, layout);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXOrigins2_65(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXOrigins2_65Controller* controller = new HyperXOrigins2_65Controller(dev, info->path, name);
RGBController_HyperXOrigins2_65* rgb_controller = new RGBController_HyperXOrigins2_65(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectHyperXEve1800(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
HyperXEve1800Controller* controller = new HyperXEve1800Controller(dev, info->path, name);
RGBController_HyperXEve1800* rgb_controller = new RGBController_HyperXEve1800(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite RGB", DetectHyperXAlloyElite, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_PID, 2, 0xFF01);
REGISTER_HID_DETECTOR_IP("HyperX Alloy FPS RGB", DetectHyperXAlloyFPS, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_FPS_RGB_PID, 2, 0xFF01);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core", DetectHyperXAlloyOriginsCore, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_PID, 2);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core (HP)", DetectHyperXAlloyOriginsCore, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_HP_PID, 2);
REGISTER_HID_DETECTOR_I("HyperX Origins 2 65 (HP)", DetectHyperXOrigins2_65, HP_KEYBOARD_VID, HYPERX_ORIGINS_2_65_HP_PID, 3);
REGISTER_HID_DETECTOR_I("HyperX Eve 1800 (HP)", DetectHyperXEve1800, HP_KEYBOARD_VID, HYPERX_EVE_1800_HP_PID, 2);
#ifdef _WIN32
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_PID, 3);
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite 2", DetectHyperXAlloyElite2, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_PID, 3, 0xFF90);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60", DetectHyperXAlloyOrigins60and65, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_PID, 3);
REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite 2 (HP)", DetectHyperXAlloyElite2, HP_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_HP_PID, 3, 0xFF90);
REGISTER_HID_DETECTOR_IP("HyperX Alloy Origins (HP)", DetectHyperXAlloyOrigins, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_HP_PID, 3, 0xFF90);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_HP_PID, 3);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 65 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_65_HP_PID, 3);
#else
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_PID, 0);
REGISTER_HID_DETECTOR_I("HyperX Alloy Elite 2", DetectHyperXAlloyElite2, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_PID, 0);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60", DetectHyperXAlloyOrigins60and65, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_PID, 0);
REGISTER_HID_DETECTOR_I("HyperX Alloy Elite 2 (HP)", DetectHyperXAlloyElite2, HP_KEYBOARD_VID, HYPERX_ALLOY_ELITE_2_HP_PID, 0);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins (HP)", DetectHyperXAlloyOrigins, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_HP_PID, 0);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 60 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_HP_PID, 0);
REGISTER_HID_DETECTOR_I("HyperX Alloy Origins 65 (HP)", DetectHyperXAlloyOrigins60and65, HP_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_65_HP_PID, 0);
#endif
@@ -0,0 +1,151 @@
/*---------------------------------------------------------*\
| HyperXOrigins2_65Controller.cpp |
| |
| Driver for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "HyperXOrigins2_65Controller.h"
#include "StringUtils.h"
HyperXOrigins2_65Controller::HyperXOrigins2_65Controller(hid_device* dev_handle, const char* path, std::string dev_name)
{
dev = dev_handle;
location = path;
name = dev_name;
}
HyperXOrigins2_65Controller::~HyperXOrigins2_65Controller()
{
hid_close(dev);
}
std::string HyperXOrigins2_65Controller::GetDeviceLocation()
{
return("HID " + location);
}
std::string HyperXOrigins2_65Controller::GetNameString()
{
return(name);
}
std::string HyperXOrigins2_65Controller::GetSerialString()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return ("");
}
return(StringUtils::wstring_to_string(serial_string));
}
void HyperXOrigins2_65Controller::SetLEDsDirect(std::vector<RGBColor> colors)
{
/*-----------------------------------------------------*\
| Set up variables to track progress of color transmit |
| Do this after inserting blanks |
\*-----------------------------------------------------*/
int colors_to_send = (int)colors.size();
int colors_sent = 0;
SendDirectInitialization();
for(int pkt_idx = 0; pkt_idx < 4; pkt_idx++)
{
if(colors_to_send > 20)
{
SendDirectColorPacket(&colors[colors_sent], 20, pkt_idx);
colors_sent += 20;
colors_to_send -= 20;
}
else if(colors_to_send > 0)
{
SendDirectColorPacket(&colors[colors_sent], colors_to_send, pkt_idx);
colors_sent += colors_to_send;
colors_to_send -= colors_to_send;
}
else
{
RGBColor temp = 0x00000000;
SendDirectColorPacket(&temp, 1, pkt_idx);
}
}
}
void HyperXOrigins2_65Controller::SendDirectInitialization()
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x44;
buf[0x01] = 0x01;
buf[0x02] = 0x04;
buf[0x03] = 0x00;
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, buf, 65);
}
void HyperXOrigins2_65Controller::SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count,
unsigned int seq
)
{
unsigned char buf[65];
/*-----------------------------------------------------*\
| Zero out buffer |
\*-----------------------------------------------------*/
memset(buf, 0x00, sizeof(buf));
/*-----------------------------------------------------*\
| Set up Direct Initialization packet |
\*-----------------------------------------------------*/
buf[0x00] = 0x44;
buf[0x01] = 0x02;
buf[0x02] = (unsigned char)seq;
buf[0x03] = 0x00;
/*-----------------------------------------------------*\
| The maximum number of colors per packet is 20 |
\*-----------------------------------------------------*/
if(color_count > 20)
{
color_count = 20;
}
/*-----------------------------------------------------*\
| Copy in color data |
\*-----------------------------------------------------*/
for(unsigned int color_idx = 0; color_idx < color_count; color_idx++)
{
buf[4 + (color_idx * 3)] = RGBGetRValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 1] = RGBGetGValue(color_data[color_idx]);
buf[4 + (color_idx * 3) + 2] = RGBGetBValue(color_data[color_idx]);
}
/*-----------------------------------------------------*\
| Send packet |
\*-----------------------------------------------------*/
hid_write(dev, buf, 65);
}
@@ -0,0 +1,43 @@
/*---------------------------------------------------------*\
| HyperXOrigins2_65Controller.h |
| |
| Driver for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <hidapi.h>
#include "RGBController.h"
class HyperXOrigins2_65Controller
{
public:
HyperXOrigins2_65Controller(hid_device* dev_handle, const char* path, std::string dev_name);
~HyperXOrigins2_65Controller();
std::string GetDeviceLocation();
std::string GetNameString();
std::string GetSerialString();
void SetLEDsDirect(std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
std::string name;
void SendDirectInitialization();
void SendDirectColorPacket
(
RGBColor* color_data,
unsigned int color_count,
unsigned int seq
);
};
@@ -0,0 +1,257 @@
/*---------------------------------------------------------*\
| RGBController_HyperXOrigins2_65.cpp |
| |
| RGBController for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBControllerKeyNames.h"
#include "RGBController_HyperXOrigins2_65.h"
using namespace std::chrono_literals;
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int matrix_map[5][15] =
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, NA, 29 },
{ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44 },
{ 45, 61, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 59 },
{ 60, 62, 63, 65, NA, NA, 66, NA, NA, 68, 69, 70, 71, 72, 73 } };
static const char* zone_names[] =
{
ZONE_EN_KEYBOARD,
};
static zone_type zone_types[] =
{
ZONE_TYPE_MATRIX,
};
static const unsigned int zone_sizes[] =
{
74,
};
static const char *led_names[] =
{
KEY_EN_ESCAPE,
KEY_EN_1,
KEY_EN_2,
KEY_EN_3,
KEY_EN_4,
KEY_EN_5,
KEY_EN_6,
KEY_EN_7,
KEY_EN_8,
KEY_EN_9,
KEY_EN_0,
KEY_EN_MINUS,
KEY_EN_EQUALS,
KEY_EN_BACKSPACE,
KEY_EN_DELETE,
KEY_EN_TAB,
KEY_EN_Q,
KEY_EN_W,
KEY_EN_E,
KEY_EN_R,
KEY_EN_T,
KEY_EN_Y,
KEY_EN_U,
KEY_EN_I,
KEY_EN_O,
KEY_EN_P,
KEY_EN_LEFT_BRACKET,
KEY_EN_RIGHT_BRACKET,
KEY_EN_UNUSED,
KEY_EN_HOME,
KEY_EN_CAPS_LOCK,
KEY_EN_A,
KEY_EN_S,
KEY_EN_D,
KEY_EN_F,
KEY_EN_G,
KEY_EN_H,
KEY_EN_J,
KEY_EN_K,
KEY_EN_L,
KEY_EN_SEMICOLON,
KEY_EN_QUOTE,
KEY_EN_POUND,
KEY_EN_ISO_ENTER,
KEY_EN_PAGE_UP,
KEY_EN_LEFT_SHIFT,
KEY_EN_Z,
KEY_EN_X,
KEY_EN_C,
KEY_EN_V,
KEY_EN_B,
KEY_EN_N,
KEY_EN_M,
KEY_EN_COMMA,
KEY_EN_PERIOD,
KEY_EN_FORWARD_SLASH,
KEY_EN_RIGHT_SHIFT,
KEY_EN_UP_ARROW,
KEY_EN_UNUSED,
KEY_EN_PAGE_DOWN,
KEY_EN_LEFT_CONTROL,
KEY_EN_ISO_BACK_SLASH,
KEY_EN_LEFT_WINDOWS,
KEY_EN_LEFT_ALT,
KEY_EN_UNUSED,
"Left Space",
KEY_EN_SPACE,
"Right Space",
KEY_EN_UNUSED,
KEY_EN_RIGHT_ALT,
KEY_EN_RIGHT_FUNCTION,
KEY_EN_LEFT_ARROW,
KEY_EN_DOWN_ARROW,
KEY_EN_RIGHT_ARROW
};
/**------------------------------------------------------------------*\
@name HyperX Origins 2 65
@category Keyboard
@type USB
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectHyperXOrigins2_65
@comment
\*-------------------------------------------------------------------*/
RGBController_HyperXOrigins2_65::RGBController_HyperXOrigins2_65(HyperXOrigins2_65Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetNameString();
vendor = "HyperX";
type = DEVICE_TYPE_KEYBOARD;
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0xFFFF;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
keepalive_thread_run = 1;
keepalive_thread = new std::thread(&RGBController_HyperXOrigins2_65::KeepaliveThread, this);
}
RGBController_HyperXOrigins2_65::~RGBController_HyperXOrigins2_65()
{
keepalive_thread_run = 0;
keepalive_thread->join();
delete keepalive_thread;
/*---------------------------------------------------------*\
| Delete the matrix map |
\*---------------------------------------------------------*/
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
{
if(zones[zone_index].matrix_map != NULL)
{
delete zones[zone_index].matrix_map;
}
}
delete controller;
}
void RGBController_HyperXOrigins2_65::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
unsigned int total_led_count = 0;
for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++)
{
zone new_zone;
new_zone.name = zone_names[zone_idx];
new_zone.type = zone_types[zone_idx];
new_zone.leds_min = zone_sizes[zone_idx];
new_zone.leds_max = zone_sizes[zone_idx];
new_zone.leds_count = zone_sizes[zone_idx];
if(zone_types[zone_idx] == ZONE_TYPE_MATRIX)
{
new_zone.matrix_map = new matrix_map_type;
new_zone.matrix_map->height = 5;
new_zone.matrix_map->width = 15;
new_zone.matrix_map->map = (unsigned int *)&matrix_map;
}
else
{
new_zone.matrix_map = NULL;
}
zones.push_back(new_zone);
total_led_count += zone_sizes[zone_idx];
}
for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++)
{
led new_led;
new_led.name = led_names[led_idx];
leds.push_back(new_led);
}
SetupColors();
}
void RGBController_HyperXOrigins2_65::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_HyperXOrigins2_65::DeviceUpdateLEDs()
{
controller->SetLEDsDirect(colors);
}
void RGBController_HyperXOrigins2_65::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXOrigins2_65::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_HyperXOrigins2_65::DeviceUpdateMode()
{
}
void RGBController_HyperXOrigins2_65::KeepaliveThread()
{
while(keepalive_thread_run.load())
{
if(active_mode == 0)
{
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50))
{
UpdateLEDs();
}
}
std::this_thread::sleep_for(10ms);;
}
}
@@ -0,0 +1,42 @@
/*---------------------------------------------------------*\
| RGBController_HyperXOrigins2_65.h |
| |
| RGBController for HyperX Origins 2 65 keyboard |
| |
| Ricardo Amorim 28 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <chrono>
#include "RGBController.h"
#include "HyperXOrigins2_65Controller.h"
class RGBController_HyperXOrigins2_65 : public RGBController
{
public:
RGBController_HyperXOrigins2_65(HyperXOrigins2_65Controller* controller_ptr);
~RGBController_HyperXOrigins2_65();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void KeepaliveThread();
private:
HyperXOrigins2_65Controller* controller;
std::thread* keepalive_thread;
std::atomic<bool> keepalive_thread_run;
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
};