diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp new file mode 100644 index 00000000..101b5312 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp @@ -0,0 +1,86 @@ +/*------------------------------------------*\ +| HyperXAlloyOriginsCoreController.cpp | +| | +| Driver for HyperX Alloy Origins Core | +| RGB Keyboard lighting controller | +| | +| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | +\*------------------------------------------*/ + +#include "HyperXAlloyOriginsCoreController.h" + +#include + +// Skip these indices in the color output +static unsigned int skip_idx[] = {6, 7, 14, 15, 22, 23, 30, 31, 38, 39, 44, 46, 47, 54, 55, 58, 60, 61, 62, 63, 70, 71, 78, 79, 86, 87, 94, 95, 101, 102, 103, 109, 110, 111, 118, 119}; + +HyperXAlloyOriginsCoreController::HyperXAlloyOriginsCoreController(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; +} + +HyperXAlloyOriginsCoreController::~HyperXAlloyOriginsCoreController() +{ + hid_close(dev); +} + +std::string HyperXAlloyOriginsCoreController::GetDeviceLocation() +{ + return("HID " + location); +} + +void HyperXAlloyOriginsCoreController::SetLEDsDirect(std::vector colors) +{ + 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); + } + + unsigned char buf[380]; + memset(buf, 0x00, sizeof(buf)); + + int offset = 0; + int rowPos = 0; + + for(unsigned int color_idx = 0; color_idx < colors.size(); color_idx++) + { + if (color_idx > 0 && color_idx % 16 == 0) + { + offset += 48; + rowPos = 0; + } + + buf[rowPos + offset] = RGBGetGValue(colors[color_idx]); + buf[rowPos + offset + 16] = RGBGetRValue(colors[color_idx]); + buf[rowPos + offset + 32] = RGBGetBValue(colors[color_idx]); + + rowPos++; + } + + unsigned int sentBytes = 0; + unsigned int bytesToSend = sizeof(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[0] = 0xA2; + packet[1] = seq++; + packet[3] = payloadSize; + + memcpy(&packet[4], &buf[sentBytes], payloadSize); + + hid_write(dev, packet, 65); + + sentBytes += payloadSize; + } +} diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h new file mode 100644 index 00000000..ea444b5d --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h @@ -0,0 +1,31 @@ +/*------------------------------------------*\ +| HyperXAlloyOriginsCoreController.h | +| | +| Definitions and types for HyperX Alloy | +| Origins Core RGB Keyboard lighting | +| controller | +| | +| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | +\*------------------------------------------*/ + +#include "RGBController.h" + +#include +#include + +#pragma once + +class HyperXAlloyOriginsCoreController +{ +public: + HyperXAlloyOriginsCoreController(hid_device* dev_handle, const char* path); + ~HyperXAlloyOriginsCoreController(); + + std::string GetDeviceLocation(); + + void SetLEDsDirect(std::vector colors); + +private: + hid_device* dev; + std::string location; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp b/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp index d7c5c25d..55ca4af3 100644 --- a/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp +++ b/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp @@ -1,10 +1,12 @@ #include "Detector.h" #include "HyperXAlloyElite2Controller.h" #include "HyperXAlloyOriginsController.h" +#include "HyperXAlloyOriginsCoreController.h" #include "HyperXKeyboardController.h" #include "RGBController.h" #include "RGBController_HyperXAlloyElite2.h" #include "RGBController_HyperXAlloyOrigins.h" +#include "RGBController_HyperXAlloyOriginsCore.h" #include "RGBController_HyperXKeyboard.h" #include @@ -41,6 +43,19 @@ void DetectHyperXAlloyOrigins(hid_device_info* info, const std::string& name) 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->path); + RGBController_HyperXAlloyOriginsCore* rgb_controller = new RGBController_HyperXAlloyOriginsCore(controller); + rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + void DetectHyperXAlloyElite2(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); @@ -57,11 +72,10 @@ REGISTER_HID_DETECTOR_IP("HyperX Alloy Elite RGB", DetectHyperXKeyboards, REGISTER_HID_DETECTOR_IP("HyperX Alloy FPS RGB", DetectHyperXKeyboards, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_FPS_RGB_PID, 2, 0xFF01); #ifdef _WIN32 -REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_PID, 3); 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); #else -REGISTER_HID_DETECTOR_I("HyperX Alloy Origins Core", DetectHyperXAlloyOrigins, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_PID, 0); 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 Core", DetectHyperXAlloyOriginsCore, HYPERX_KEYBOARD_VID, HYPERX_ALLOY_ORIGINS_CORE_PID, 2); #endif diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp new file mode 100644 index 00000000..88f7860b --- /dev/null +++ b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp @@ -0,0 +1,279 @@ +/*------------------------------------------*\ +| RGBController_HyperXAlloyOriginsCore.cpp | +| | +| Generic RGB Interface for HyperX Alloy | +| Origins Core RGB Keyboard | +| | +| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | +\*------------------------------------------*/ + +#include "RGBController_HyperXAlloyOriginsCore.h" + +using namespace std::chrono_literals; + +//0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +static unsigned int matrix_map[6][19] = +{ + { 0, NA, 1, 2, 3, 4, 5, 6, 7, 44, NA, 45, 46, 47, 48, NA, 49, 50, 51 }, + { 8, 9, 10, 11, 12, 13, 14, 15, 16, 52, 53, 54, 55, 56, NA, NA, 57, 58, 59 }, + { 17, NA, 18, 19, 20, 21, 22, 23, 24, 60, 61, 62, 63, 64, 65, NA, 66, 67, 68 }, + { 25, NA, 26, 27, 28, 29, 30, 31, 32, 69, 70, 71, 72, 73, NA, NA, NA, NA, NA }, + { 33, NA, 34, 35, 36, 37, 38, NA, 39, 74, 75, 76, 77, 78, NA, NA, NA, 79, NA }, + { 40, 41, 42, NA, NA, NA, 43, NA, NA, NA, NA, 80, 81, 82, 83, NA, 84, 85, 86 } +}; + +static const char* zone_names[] = +{ + "Keyboard", +}; + +static zone_type zone_types[] = +{ + ZONE_TYPE_MATRIX, +}; + +static const unsigned int zone_sizes[] = +{ + 87, +}; + +static const char *led_names[] = +{ + "Key: Escape", + "Key: F1", + "Key: F2", + "Key: F3", + "Key: F4", + "Key: F5", + "Key: F6", + "Key: F7", + + "Key: `", + "Key: 1", + "Key: 2", + "Key: 3", + "Key: 4", + "Key: 5", + "Key: 6", + "Key: 7", + "Key: 8", + + "Key: Tab", + "Key: Q", + "Key: W", + "Key: E", + "Key: R", + "Key: T", + "Key: Y", + "Key: U", + + "Key: Caps Lock", + "Key: A", + "Key: S", + "Key: D", + "Key: F", + "Key: G", + "Key: H", + "Key: J", + + "Key: Left Shift", + "Key: Z", + "Key: X", + "Key: C", + "Key: V", + "Key: B", + "Key: N", + + "Key: Left Control", + "Key: Left Windows", + "Key: Left Alt", + "Key: Space", + + // End of first section + + "Key: F8", + "Key: F9", + "Key: F10", + "Key: F11", + "Key: F12", + "Key: Print Screen", + "Key: Scroll Lock", + "Key: Pause/Break", + + "Key: 9", + "Key: 0", + "Key: -", + "Key: =", + "Key: Backspace", + "Key: Insert", + "Key: Page Up", + "Key: Home", + + + "Key: I", + "Key: O", + "Key: P", + "Key: [", + "Key: ]", + "Key: \\ (ANSI)", + "Key: Delete", + "Key: Page Down", + "Key: End", + + + "Key: K", + "Key: L", + "Key: ;", + "Key: '", + "Key: Enter", + + + "Key: M", + "Key: ,", + "Key: .", + "Key: /", + "Key: Right Shift", + "Key: Up Arrow", + "Key: Right Alt", + "Key: Right Fn", + "Key: Menu", + "Key: Right Control", + "Key: Left Arrow", + "Key: Down Arrow", + "Key: Right Arrow" +}; + +RGBController_HyperXAlloyOriginsCore::RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* hyperx_ptr) +{ + hyperx = hyperx_ptr; + + name = "HyperX Alloy Origins Core Keyboard Device"; + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + description = "HyperX Alloy Origins Core Keyboard Device"; + location = hyperx->GetDeviceLocation(); + serial = ""; + + 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 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 hyperx; +} + +void RGBController_HyperXAlloyOriginsCore::SetupZones() +{ + 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 = 19; + 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_HyperXAlloyOriginsCore::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HyperXAlloyOriginsCore::DeviceUpdateLEDs() +{ + hyperx->SetLEDsDirect(colors); +} + +void RGBController_HyperXAlloyOriginsCore::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXAlloyOriginsCore::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXAlloyOriginsCore::SetCustomMode() +{ + +} + +void RGBController_HyperXAlloyOriginsCore::DeviceUpdateMode() +{ + +} + +void RGBController_HyperXAlloyOriginsCore::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if(active_mode == 0) + { + DeviceUpdateLEDs(); + } + std::this_thread::sleep_for(10ms); + } +} diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h new file mode 100644 index 00000000..70e89938 --- /dev/null +++ b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h @@ -0,0 +1,39 @@ +/*------------------------------------------*\ +| RGBController_HyperXAlloyOriginsCore.h | +| | +| Generic RGB Interface for HyperX Alloy | +| Origins Core RGB Keyboard | +| | +| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | +\*------------------------------------------*/ + +#pragma once +#include + +#include "RGBController.h" +#include "HyperXAlloyOriginsCoreController.h" + +class RGBController_HyperXAlloyOriginsCore : public RGBController +{ +public: + RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* hyperx_ptr); + ~RGBController_HyperXAlloyOriginsCore(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void SetCustomMode(); + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXAlloyOriginsCoreController* hyperx; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index 9625572f..ec29354d 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -271,9 +271,11 @@ HEADERS += Controllers/HyperXDRAMController/RGBController_HyperXDRAM.h \ Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.h \ Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.h \ + Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h \ Controllers/HyperXKeyboardController/HyperXKeyboardController.h \ Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.h \ Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.h \ + Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h \ Controllers/HyperXKeyboardController/RGBController_HyperXKeyboard.h \ Controllers/HyperXMouseController/HyperXPulsefireFPSProController.h \ Controllers/HyperXMouseController/HyperXPulsefireSurgeController.h \ @@ -590,10 +592,12 @@ SOURCES += Controllers/HyperXDRAMController/RGBController_HyperXDRAM.cpp \ Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.cpp \ Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.cpp \ + Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp \ Controllers/HyperXKeyboardController/HyperXKeyboardController.cpp \ Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp \ Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.cpp \ Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.cpp \ + Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp \ Controllers/HyperXKeyboardController/RGBController_HyperXKeyboard.cpp \ Controllers/HyperXMouseController/HyperXMouseControllerDetect.cpp \ Controllers/HyperXMouseController/HyperXPulsefireFPSProController.cpp \