From 79471ad42c276ab3d7c4239ebfa61f77b5431080 Mon Sep 17 00:00:00 2001 From: Derek Huber Date: Mon, 24 Oct 2022 02:10:13 -0500 Subject: [PATCH] HyperX Alloy Origins 60 initial commit --- .../HyperXAlloyOrigins60Controller.cpp | 143 ++++++++++ .../HyperXAlloyOrigins60Controller.h | 39 +++ .../HyperXKeyboardControllerDetect.cpp | 22 +- .../RGBController_HyperXAlloyOrigins60.cpp | 262 ++++++++++++++++++ .../RGBController_HyperXAlloyOrigins60.h | 39 +++ OpenRGB.pro | 4 + 6 files changed, 507 insertions(+), 2 deletions(-) create mode 100644 Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.cpp create mode 100644 Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.h create mode 100644 Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.cpp create mode 100644 Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.h diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.cpp new file mode 100644 index 00000000..e819583f --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.cpp @@ -0,0 +1,143 @@ +/*-----------------------------------------*\ +| HyperXAlloyOrigins60Controller.cpp | +| | +| Driver for HyperX Alloy Origins 60 RGB | +| Keyboard lighting controller | +| | +| Derek Huber 10/24/2022 | +\*-----------------------------------------*/ + +#include "HyperXAlloyOrigins60Controller.h" + +#include + +HyperXAlloyOrigins60Controller::HyperXAlloyOrigins60Controller(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; +} + +HyperXAlloyOrigins60Controller::~HyperXAlloyOrigins60Controller() +{ + hid_close(dev); +} + +std::string HyperXAlloyOrigins60Controller::GetDeviceLocation() +{ + return("HID " + location); +} + +std::string HyperXAlloyOrigins60Controller::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + std::wstring return_wstring = serial_string; + std::string return_string(return_wstring.begin(), return_wstring.end()); + + return(return_string); +} + +void HyperXAlloyOrigins60Controller::SetLEDsDirect(std::vector colors) +{ + /*-----------------------------------------------------*\ + | Set up variables to track progress of color transmit | + | Do this after inserting blanks | + \*-----------------------------------------------------*/ + int colors_to_send = 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 HyperXAlloyOrigins60Controller::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 HyperXAlloyOrigins60Controller::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); +} diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.h b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.h new file mode 100644 index 00000000..c43e926b --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.h @@ -0,0 +1,39 @@ +/*-----------------------------------------*\ +| HyperXAlloyOrigins60Controller.h | +| | +| Definitions and types for HyperX Alloy | +| Origins 60 RGB Keyboard lighting | +| controller | +| | +| Derek Huber 10/24/2022 | +\*-----------------------------------------*/ + +#include "RGBController.h" + +#include +#include + +#pragma once + +class HyperXAlloyOrigins60Controller +{ +public: + HyperXAlloyOrigins60Controller(hid_device* dev_handle, const char* path); + ~HyperXAlloyOrigins60Controller(); + + std::string GetDeviceLocation(); + std::string GetSerialString(); + + void SetLEDsDirect(std::vector colors); + +private: + hid_device* dev; + std::string location; + + void SendDirectInitialization(); + void SendDirectColorPacket + ( + RGBColor* color_data, + unsigned int color_count + ); +}; diff --git a/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp b/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp index a1e359d3..c8940669 100644 --- a/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp +++ b/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp @@ -4,12 +4,14 @@ #include "HyperXAlloyFPSController.h" #include "HyperXAlloyOriginsController.h" #include "HyperXAlloyOriginsCoreController.h" +#include "HyperXAlloyOrigins60Controller.h" #include "RGBController.h" #include "RGBController_HyperXAlloyElite.h" #include "RGBController_HyperXAlloyElite2.h" #include "RGBController_HyperXAlloyFPS.h" #include "RGBController_HyperXAlloyOrigins.h" #include "RGBController_HyperXAlloyOriginsCore.h" +#include "RGBController_HyperXAlloyOrigins60.h" #include /*-----------------------------------------------------*\ @@ -22,6 +24,7 @@ #define HYPERX_ALLOY_ORIGINS_PID 0x16E5 #define HYPERX_ALLOY_ORIGINS_V2_PID 0x0591 #define HYPERX_ALLOY_ORIGINS_CORE_PID 0x16E6 +#define HYPERX_ALLOY_ORIGINS_60_PID 0x1734 #define HP_KEYBOARD_VID 0x03F0 #define HYPERX_ALLOY_ELITE_2_HP_PID 0x058F @@ -71,7 +74,7 @@ void DetectHyperXAlloyFPS(hid_device_info* info, const std::string& name) 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); @@ -91,7 +94,21 @@ void DetectHyperXAlloyOriginsCore(hid_device_info* info, const std::string& name HyperXAlloyOriginsCoreController* controller = new HyperXAlloyOriginsCoreController(dev, info); RGBController_HyperXAlloyOriginsCore* rgb_controller = new RGBController_HyperXAlloyOriginsCore(controller); rgb_controller->name = name; - + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectHyperXAlloyOrigins60(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + HyperXAlloyOrigins60Controller* controller = new HyperXAlloyOrigins60Controller(dev, info->path); + RGBController_HyperXAlloyOrigins60* rgb_controller = new RGBController_HyperXAlloyOrigins60(controller); + rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -99,6 +116,7 @@ void DetectHyperXAlloyOriginsCore(hid_device_info* info, const std::string& name 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 60", DetectHyperXAlloyOrigins60, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_60_PID, 3); #ifdef _WIN32 REGISTER_HID_DETECTOR_I("HyperX Alloy Origins", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_PID, 3); diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.cpp b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.cpp new file mode 100644 index 00000000..572b3b7a --- /dev/null +++ b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.cpp @@ -0,0 +1,262 @@ +/*-----------------------------------------*\ +| RGBController_HyperXAlloyOrigins60.cpp | +| | +| Generic RGB Interface for HyperX Alloy | +| Origins 60 RGB Keyboard | +| | +| Derek Huber 10/24/2022 | +\*-----------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_HyperXAlloyOrigins60.h" + +using namespace std::chrono_literals; + +//0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +static unsigned int matrix_map[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 const char* zone_names[] = +{ + ZONE_EN_KEYBOARD +}; + +static zone_type zone_types[] = +{ + ZONE_TYPE_MATRIX +}; + +static const unsigned int zone_sizes[] = +{ + 71 +}; + +static const char *led_names[] = +{ + // 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, + KEY_EN_UNUSED, + KEY_EN_SPACE, + KEY_EN_UNUSED, + KEY_EN_RIGHT_ALT, + KEY_EN_MENU, + KEY_EN_RIGHT_CONTROL, + KEY_EN_UNUSED, + KEY_EN_UNUSED, + KEY_EN_UNUSED, + KEY_EN_RIGHT_FUNCTION +}; + +/**------------------------------------------------------------------*\ + @name HyperX Alloy Origins 60 + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectHyperXAlloyOrigins60 + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HyperXAlloyOrigins60::RGBController_HyperXAlloyOrigins60(HyperXAlloyOrigins60Controller* controller_ptr) +{ + controller = controller_ptr; + + name = "HyperX Alloy Origins 60 Keyboard Device"; + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + description = "HyperX Alloy Origins 60 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(); + + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_HyperXAlloyOrigins60::KeepaliveThread, this); +} + +RGBController_HyperXAlloyOrigins60::~RGBController_HyperXAlloyOrigins60() +{ + 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_HyperXAlloyOrigins60::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 = 14; + 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_HyperXAlloyOrigins60::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HyperXAlloyOrigins60::DeviceUpdateLEDs() +{ + controller->SetLEDsDirect(colors); +} + +void RGBController_HyperXAlloyOrigins60::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXAlloyOrigins60::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXAlloyOrigins60::DeviceUpdateMode() +{ + +} + +void RGBController_HyperXAlloyOrigins60::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);; + } +} diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.h new file mode 100644 index 00000000..4eceb0e3 --- /dev/null +++ b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.h @@ -0,0 +1,39 @@ +/*-----------------------------------------*\ +| RGBController_HyperXAlloyOrigins60.h | +| | +| Generic RGB Interface for HyperX Alloy | +| Origins 60 RGB Keyboard | +| | +| Derek Huber 10/24/2022 | +\*-----------------------------------------*/ + +#pragma once +#include + +#include "RGBController.h" +#include "HyperXAlloyOrigins60Controller.h" + +class RGBController_HyperXAlloyOrigins60 : public RGBController +{ +public: + RGBController_HyperXAlloyOrigins60(HyperXAlloyOrigins60Controller* controller_ptr); + ~RGBController_HyperXAlloyOrigins60(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXAlloyOrigins60Controller* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index 5e132e00..e9a66591 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -176,6 +176,8 @@ contains(QMAKE_PLATFORM, freebsd) { HEADERS += \ Colors.h \ + Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.h \ + Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.h \ dependencies/ColorWheel/ColorWheel.h \ dependencies/Swatches/swatches.h \ dependencies/json/json.hpp \ @@ -634,6 +636,8 @@ contains(QMAKE_PLATFORM, freebsd) { } SOURCES += \ + Controllers/HyperXKeyboardController/HyperXAlloyOrigins60Controller.cpp \ + Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60.cpp \ dependencies/Swatches/swatches.cpp \ dependencies/dmiinfo.cpp \ dependencies/ColorWheel/ColorWheel.cpp \