From 8255af7fe75cb95dfe0b0d9e8b7b6a6ddcd40362 Mon Sep 17 00:00:00 2001 From: NicolasNewman Date: Thu, 25 Mar 2021 15:14:56 -0400 Subject: [PATCH] alpha support for XPG S40G --- .../RGBController_XPGSpectrixS40G.cpp | 333 ++++++++++++++++++ .../RGBController_XPGSpectrixS40G.h | 34 ++ .../XPGSpectrixS40GController.cpp | 163 +++++++++ .../XPGSpectrixS40GController.h | 138 ++++++++ .../XPGSpectrixS40GControllerDetect.cpp | 82 +++++ OpenRGB.pro | 6 + RGBController/RGBController.cpp | 2 + RGBController/RGBController.h | 1 + qt/OpenRGBDialog2.cpp | 3 + qt/resources.qrc | 2 + qt/storage.png | Bin 0 -> 2930 bytes qt/storage_dark.png | Bin 0 -> 2915 bytes 12 files changed, 764 insertions(+) create mode 100644 Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.cpp create mode 100644 Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.h create mode 100644 Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.cpp create mode 100644 Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.h create mode 100644 Controllers/XPGSpectrixS40GController/XPGSpectrixS40GControllerDetect.cpp create mode 100644 qt/storage.png create mode 100644 qt/storage_dark.png diff --git a/Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.cpp b/Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.cpp new file mode 100644 index 000000000..e356c04bb --- /dev/null +++ b/Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.cpp @@ -0,0 +1,333 @@ +/*-------------------------------------------------------------------*\ +| RGBController_XPGSpectrixS40G.cpp | +| | +| Driver for XPG's Spectrix S40G NVMe | +| | +| NicolasNewman 25th Mar 2021 | +| | +\*-------------------------------------------------------------------*/ + +#include "RGBController_XPGSpectrixS40G.h" + +RGBController_XPGSpectrixS40G::RGBController_XPGSpectrixS40G(XPGSpectrixS40GController* spectrix_ptr) +{ + xpg = spectrix_ptr; + + name = "XPG Spectrix S40G"; + vendor = "XPG"; + type = DEVICE_TYPE_STORAGE; + description = "XPG Spectrix S40G RGB NVMe"; + + mode Static; + Static.name = "Static"; + Static.value = XPG_SPECTRIX_S40G_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = XPG_SPECTRIX_S40G_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED; + Breathing.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + Breathing.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + Breathing.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + mode Strobing; + Strobing.name = "Strobing"; + Strobing.value = XPG_SPECTRIX_S40G_MODE_STROBING; + Strobing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED; + Strobing.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + Strobing.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + Strobing.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + Strobing.color_mode = MODE_COLORS_PER_LED; + + mode Cycle; + Cycle.name = "Cycle"; + Cycle.value = XPG_SPECTRIX_S40G_MODE_CYCLE; + Cycle.flags = MODE_FLAG_HAS_SPEED; // MODE SPECIFIC COLOR correct...? + Cycle.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + Cycle.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + Cycle.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + Cycle.color_mode = MODE_COLORS_NONE; + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = XPG_SPECTRIX_S40G_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Rainbow.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + Rainbow.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + Rainbow.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + Rainbow.direction = MODE_DIRECTION_RIGHT; + Rainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(Rainbow); + + mode BreathingRainbow; + BreathingRainbow.name = "Breathing Rainbow"; + BreathingRainbow.value = XPG_SPECTRIX_S40G_MODE_BREATHING_RAINBOW; + BreathingRainbow.flags = MODE_FLAG_HAS_SPEED; + BreathingRainbow.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + BreathingRainbow.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + BreathingRainbow.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + BreathingRainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(BreathingRainbow); + + // mode Comet; + // Comet.name = "Comet"; + // Comet.value = XPG_SPECTRIX_S40G_MODE_COMET; + // Comet.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + // Comet.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + // Comet.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + // Comet.colors_min = 1; + // Comet.colors_max = 1; + // Comet.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + // Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; + // Comet.colors.resize(1); + // modes.push_back(Comet); + + mode CometRainbow; + CometRainbow.name = "Comet Rainbow"; + CometRainbow.value = XPG_SPECTRIX_S40G_MODE_COMET_RAINBOW; + CometRainbow.flags = MODE_FLAG_HAS_SPEED; + CometRainbow.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + CometRainbow.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + CometRainbow.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + CometRainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(CometRainbow); + + // mode Flash; + // Flash.name = "Flash"; + // Flash.value = XPG_SPECTRIX_S40G_MODE_FLASH; + + // TODO not functioning properly + // mode FlashRainbow; + // FlashRainbow.name = "Flash Rainbow"; + // FlashRainbow.value = XPG_SPECTRIX_S40G_MODE_FLASH_RAINBOW; + // FlashRainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + // FlashRainbow.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + // FlashRainbow.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + // FlashRainbow.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + // FlashRainbow.direction = MODE_DIRECTION_RIGHT; + // FlashRainbow.color_mode = MODE_COLORS_NONE; + // modes.push_back(FlashRainbow); + + // TODO not functioning properly + // mode Wave; + // Wave.name = "Wave"; + // Wave.value = XPG_SPECTRIX_S40G_MODE_WAVE; + // Wave.flags = MODE_FLAG_HAS_SPEED; + // Wave.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + // Wave.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + // Wave.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + // Wave.color_mode = MODE_COLORS_NONE; + // modes.push_back(Wave); + + // TODO not functioning properly + // mode GlowingYoyo; + // GlowingYoyo.name = "Glowing Yoyo"; + // GlowingYoyo.value = XPG_SPECTRIX_S40G_MODE_YOYO; + // GlowingYoyo.flags = MODE_FLAG_HAS_SPEED; + // GlowingYoyo.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + // GlowingYoyo.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + // GlowingYoyo.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + // GlowingYoyo.color_mode = MODE_COLORS_NONE; + // modes.push_back(GlowingYoyo); + + // TODO not functioning properly + // mode StarryNight; + // StarryNight.name = "Starry Night"; + // StarryNight.value = XPG_SPECTRIX_S40G_MODE_STARRY_NIGHT; + // StarryNight.flags = MODE_FLAG_HAS_SPEED; + // StarryNight.speed_min = XPG_SPECTRIX_S40G_SPEED_SLOWEST; + // StarryNight.speed_max = XPG_SPECTRIX_S40G_SPEED_FASTEST; + // StarryNight.speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; + // StarryNight.color_mode = MODE_COLORS_NONE; + // modes.push_back(StarryNight); + + SetupZones(); +} + +RGBController_XPGSpectrixS40G::~RGBController_XPGSpectrixS40G() +{ + delete xpg; +} + +void RGBController_XPGSpectrixS40G::SetupZones() +{ + zone new_zone; + new_zone.name = "XPG Spectrix S40G Zone"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = xpg->GetLEDCount(); + new_zone.leds_max = xpg->GetLEDCount(); + new_zone.leds_count = xpg->GetLEDCount(); + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + for(std::size_t led_indx = 0; led_indx < zones[0].leds_count; led_indx++) + { + led* new_led = new led(); + new_led->name = "XPG Spectrix LED "; + new_led->name.append(std::to_string(led_indx)); + leds.push_back(*new_led); + } + + SetupColors(); +} + +void RGBController_XPGSpectrixS40G::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_XPGSpectrixS40G::DeviceUpdateLEDs() { + for (std::size_t led = 0; led < colors.size(); led++) + { + RGBColor color = colors[led]; + uint8_t red = RGBGetRValue(color); + uint8_t grn = RGBGetGValue(color); + uint8_t blu = RGBGetBValue(color); + + xpg->SetLEDColor(led, red, grn, blu); + } + + xpg->ApplyColors(); +} + +void RGBController_XPGSpectrixS40G::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_XPGSpectrixS40G::UpdateSingleLED(int led) +{ + RGBColor color = colors[led]; + uint8_t red = RGBGetRValue(color); + uint8_t grn = RGBGetGValue(color); + uint8_t blu = RGBGetBValue(color); + + xpg->SetLEDColor(led, red, grn, blu); + xpg->ApplyColors(); +} + +void RGBController_XPGSpectrixS40G::SetCustomMode() // TODO +{ + active_mode = 0; +} + +void RGBController_XPGSpectrixS40G::DeviceUpdateMode() +{ + uint8_t direction = 0; + uint8_t speed = 0x0; + uint8_t mode_colors[3]; + + switch(modes[active_mode].direction) + { + case MODE_DIRECTION_RIGHT: + direction = XPG_SPECTRIX_S40G_DIRECTION_DEFAULT; + break; + case MODE_DIRECTION_LEFT: + direction = XPG_SPECTRIX_S40G_DIRECTION_REVERSE; + break; + default: + direction = 0x00; + } + + switch(modes[active_mode].speed) + { + case XPG_SPECTRIX_S40G_SPEED_SLOWEST: + speed = 0xFF; + break; + case XPG_SPECTRIX_S40G_SPEED_SLOW: + speed = 0xFE; + break; + case XPG_SPECTRIX_S40G_SPEED_NORMAL: + speed = 0x00; + break; + case XPG_SPECTRIX_S40G_SPEED_FAST: + speed = 0x01; + break; + case XPG_SPECTRIX_S40G_SPEED_FASTEST: + speed = 0x02; + break; + default: + speed = 0x00; + } + + mode_colors[0] = 0; + mode_colors[1] = 0; + mode_colors[2] = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + mode_colors[0] = RGBGetRValue(modes[active_mode].colors[0]); + mode_colors[1] = RGBGetGValue(modes[active_mode].colors[0]); + mode_colors[2] = RGBGetBValue(modes[active_mode].colors[0]); + } + + xpg->SetDirection(0x00); + xpg->SetSpeed(0x00); + switch(modes[active_mode].value) + { + case XPG_SPECTRIX_S40G_MODE_STATIC: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_STATIC); + break; + case XPG_SPECTRIX_S40G_MODE_BREATHING: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_BREATHING); + xpg->SetSpeed(speed); + break; + case XPG_SPECTRIX_S40G_MODE_STROBING: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_STROBING); + xpg->SetSpeed(speed); + break; + case XPG_SPECTRIX_S40G_MODE_CYCLE: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_CYCLE); + xpg->SetSpeed(speed); + break; + case XPG_SPECTRIX_S40G_MODE_RAINBOW: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_RAINBOW); + xpg->SetSpeed(speed); + xpg->SetDirection(direction); + break; + case XPG_SPECTRIX_S40G_MODE_BREATHING_RAINBOW: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_BREATHING_RAINBOW); + xpg->SetSpeed(speed); + break; + case XPG_SPECTRIX_S40G_MODE_COMET: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_COMET); + xpg->SetSpeed(speed); + xpg->SetAllColors(mode_colors[0], mode_colors[1], mode_colors[2]); + break; + case XPG_SPECTRIX_S40G_MODE_COMET_RAINBOW: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_COMET_RAINBOW); + xpg->SetSpeed(speed); + break; + case XPG_SPECTRIX_S40G_MODE_FLASH: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_FLASH); + xpg->SetSpeed(speed); + xpg->SetDirection(direction); + xpg->SetAllColors(mode_colors[0], mode_colors[1], mode_colors[2]); + break; + case XPG_SPECTRIX_S40G_MODE_FLASH_RAINBOW: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_FLASH_RAINBOW); + xpg->SetSpeed(speed); + xpg->SetDirection(direction); + break; + case XPG_SPECTRIX_S40G_MODE_WAVE: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_WAVE); + xpg->SetSpeed(speed); + break; + case XPG_SPECTRIX_S40G_MODE_YOYO: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_YOYO); + xpg->SetSpeed(speed); + break; + case XPG_SPECTRIX_S40G_MODE_STARRY_NIGHT: + xpg->SetMode(XPG_SPECTRIX_S40G_MODE_STARRY_NIGHT); + xpg->SetSpeed(speed); + break; + } + xpg->ApplyColors(); +} diff --git a/Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.h b/Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.h new file mode 100644 index 000000000..b3069cba7 --- /dev/null +++ b/Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.h @@ -0,0 +1,34 @@ +/*-------------------------------------------------------------------*\ +| RGBController_XPGSpectrixS40G.h | +| | +| Driver for XPG's Spectrix S40G NVMe | +| | +| NicolasNewman 25th Mar 2021 | +| | +\*-------------------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "XPGSpectrixS40GController.h" + +class RGBController_XPGSpectrixS40G : public RGBController +{ +public: + RGBController_XPGSpectrixS40G(XPGSpectrixS40GController* spectrix_ptr); + ~RGBController_XPGSpectrixS40G(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void SetCustomMode(); + void DeviceUpdateMode(); + +private: + XPGSpectrixS40GController* xpg; +}; diff --git a/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.cpp b/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.cpp new file mode 100644 index 000000000..33180537d --- /dev/null +++ b/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.cpp @@ -0,0 +1,163 @@ +/*-------------------------------------------------------------------*\ +| XPGSpectrixS40GController.cpp | +| | +| Driver for XPG's Spectrix S40G NVMe | +| | +| NicolasNewman 25th Mar 2021 | +| | +\*-------------------------------------------------------------------*/ + +#include "XPGSpectrixS40GController.h" +#include +#include + +#ifdef _WIN32 + #include + #include +#else + +#endif + +XPGSpectrixS40GController::XPGSpectrixS40GController() +{ + led_count = XPG_SPECTRIX_LED_COUNT; + InitializePackets(); + + active_mode = XPG_SPECTRIX_S40G_MODE_STATIC; + active_direction = XPG_SPECTRIX_S40G_DIRECTION_DEFAULT; + active_speed = XPG_SPECTRIX_S40G_SPEED_NORMAL; +} + +#ifdef _WIN32 + int XPGSpectrixS40GController::SetHandle(wchar_t buff[MAX_PATH]) { + wchar_t path[MAX_PATH]; + wcscpy(path, L"\\\\?\\"); + wcsncat(path, buff, MAX_PATH - 4); + for (size_t i = 0; i < MAX_PATH && path[i] != '\0'; i++) { + path[i] = tolower(path[i]); + } + wprintf(L"%s\n", path); + hDevice = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)0x0, OPEN_EXISTING, 0x0, (HANDLE)0x0); + if (hDevice == INVALID_HANDLE_VALUE) { + return 0; + } + return 1; + } +#else + +#endif + +unsigned int XPGSpectrixS40GController::GetLEDCount() +{ + return led_count; +} + +void XPGSpectrixS40GController::ApplyColors() +{ + #ifdef _WIN32 + for (unsigned int i = 0; i < BIG_PACKET_SIZE / 4; i++) { + if (i % 10 == 0) { + } + } + for (unsigned int i = 0; i < SMALL_PACKET_SIZE / 4; i++) { + if (i % 10 == 0) { + } + } + // TODO better error detection + if (hDevice != INVALID_HANDLE_VALUE) { + int out = DeviceIoControl(hDevice, 0x2dd3c0, packet_one, BIG_PACKET_SIZE, packet_one, BIG_PACKET_SIZE, 0x0, (LPOVERLAPPED)0x0); + if (out > 0) { + out = DeviceIoControl(hDevice, 0x2dd3c0, packet_two, SMALL_PACKET_SIZE, packet_two, SMALL_PACKET_SIZE, 0x0, (LPOVERLAPPED)0x0); + } + if (out > 0) { + out = DeviceIoControl(hDevice, 0x2dd3c0, packet_three, SMALL_PACKET_SIZE, packet_three, SMALL_PACKET_SIZE, 0x0, (LPOVERLAPPED)0x0); + } + } + #else + + #endif +} + +XPGSpectrixS40GController::~XPGSpectrixS40GController() +{ + free(packet_one); + packet_one = NULL; + free(packet_two); + packet_two = NULL; + free(packet_three); + packet_three = NULL; +} + +void XPGSpectrixS40GController::InitializePackets() { + packet_one = (uint32_t *) malloc(BIG_PACKET_SIZE); + packet_two = (uint32_t *) malloc(SMALL_PACKET_SIZE); + packet_three = (uint32_t *) malloc(SMALL_PACKET_SIZE); + memcpy(packet_one, packet_one_template, BIG_PACKET_SIZE); + memcpy(packet_two, packet_two_template, SMALL_PACKET_SIZE); + memcpy(packet_three, packet_three_template, SMALL_PACKET_SIZE); +} + +void XPGSpectrixS40GController::SetMode(uint8_t mode) { + *((uint8_t *) (packet_two+52)+1) = mode; +} + +void XPGSpectrixS40GController::SetSpeed(uint8_t speed) { + *((uint8_t *) (packet_two+52)+2) = speed; +} + +void XPGSpectrixS40GController::SetDirection(uint8_t direction) { + *((uint8_t *) (packet_three+52)+3) = direction; +} + +void XPGSpectrixS40GController::SetAllColors(uint8_t r, uint8_t g, uint8_t b) { + for (unsigned int i = 0; i < led_count; i++) { + SetLEDColor(i, r, g, b); + } +} + +void XPGSpectrixS40GController::SetLEDColor(unsigned int led, uint8_t r, uint8_t g, uint8_t b) { + switch(led) { + case 0x0: + *((uint8_t *) (packet_one+52)+0) = r; + *((uint8_t *) (packet_one+52)+1) = b; + *((uint8_t *) (packet_one+52)+2) = g; + break; + case 0x1: + *((uint8_t *) (packet_one+52)+3) = r; + *((uint8_t *) (packet_one+53)+0) = b; + *((uint8_t *) (packet_one+53)+1) = g; + break; + case 0x2: + *((uint8_t *) (packet_one+53)+2) = r; + *((uint8_t *) (packet_one+53)+3) = b; + *((uint8_t *) (packet_one+54)+0) = g; + break; + case 0x3: + *((uint8_t *) (packet_one+54)+1) = r; + *((uint8_t *) (packet_one+54)+2) = b; + *((uint8_t *) (packet_one+54)+3) = g; + break; + case 0x4: + *((uint8_t *) (packet_one+55)+0) = r; + *((uint8_t *) (packet_one+55)+1) = b; + *((uint8_t *) (packet_one+55)+2) = g; + break; + case 0x5: + *((uint8_t *) (packet_one+55)+3) = r; + *((uint8_t *) (packet_one+56)+0) = b; + *((uint8_t *) (packet_one+56)+1) = g; + break; + case 0x6: + *((uint8_t *) (packet_one+56)+2) = r; + *((uint8_t *) (packet_one+56)+3) = b; + *((uint8_t *) (packet_one+57)+0) = g; + break; + case 0x7: + *((uint8_t *) (packet_one+57)+1) = r; + *((uint8_t *) (packet_one+57)+2) = b; + *((uint8_t *) (packet_one+57)+3) = g; + break; + default: + return; + } +} diff --git a/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.h b/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.h new file mode 100644 index 000000000..149a2e984 --- /dev/null +++ b/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.h @@ -0,0 +1,138 @@ +/*-------------------------------------------------------------------*\ +| XPGSpectrixS40GController.h | +| | +| Driver for XPG's Spectrix S40G NVMe | +| | +| NicolasNewman 25th Mar 2021 | +| | +\*-------------------------------------------------------------------*/ + +#include "RGBController.h" +#include +#include +#include + +#pragma once + +#define XPG_SPECTRIX_LED_COUNT ( 8 ) +#define BIG_PACKET_SIZE ( 236 ) +#define SMALL_PACKET_SIZE ( 216 ) + +#ifdef _WIN32 + #include + #include +#else + +#endif + +enum +{ + XPG_SPECTRIX_S40G_MODE_STATIC = 0x01, + XPG_SPECTRIX_S40G_MODE_BREATHING = 0x02, + XPG_SPECTRIX_S40G_MODE_STROBING = 0x03, + XPG_SPECTRIX_S40G_MODE_CYCLE = 0x04, + XPG_SPECTRIX_S40G_MODE_RAINBOW = 0x05, + XPG_SPECTRIX_S40G_MODE_BREATHING_RAINBOW = 0x06, + XPG_SPECTRIX_S40G_MODE_COMET = 0x07, + XPG_SPECTRIX_S40G_MODE_COMET_RAINBOW = 0x08, + XPG_SPECTRIX_S40G_MODE_FLASH = 0x09, + XPG_SPECTRIX_S40G_MODE_FLASH_RAINBOW = 0x10, + XPG_SPECTRIX_S40G_MODE_WAVE = 0x11, + XPG_SPECTRIX_S40G_MODE_YOYO = 0x12, + XPG_SPECTRIX_S40G_MODE_STARRY_NIGHT = 0x13, +}; + +enum +{ + XPG_SPECTRIX_S40G_SPEED_SLOWEST = 0x00, // 0xfe + XPG_SPECTRIX_S40G_SPEED_SLOW = 0x01, // 0xff + XPG_SPECTRIX_S40G_SPEED_NORMAL = 0x02, // 0x00 + XPG_SPECTRIX_S40G_SPEED_FAST = 0x03, // 0x01 + XPG_SPECTRIX_S40G_SPEED_FASTEST = 0x04, // 0x02 +}; + +enum +{ + XPG_SPECTRIX_S40G_DIRECTION_DEFAULT = 0x0, + XPG_SPECTRIX_S40G_DIRECTION_REVERSE = 0x1, +}; + +class XPGSpectrixS40GController +{ + public: + XPGSpectrixS40GController(); + ~XPGSpectrixS40GController(); + + #ifdef _WIN32 + /*-----------------------------------------------------*\ + | Windows specific function that allows the devices | + | handle to be passed from elsewhere once detected | + \*-----------------------------------------------------*/ + int SetHandle(wchar_t dev_name[MAX_PATH]); + #else + + #endif + + unsigned char GetEffect(); + void SetEffect(unsigned char mode, + unsigned char speed, + unsigned char direction, + uint8_t mode_colors[] + ); + void SetMode(unsigned char mode); + void SetSpeed(unsigned char speed); + void SetDirection(unsigned char direction); + + unsigned int GetLEDCount(); + void SetAllColors(uint8_t red, uint8_t green, uint8_t blue); + void SetLEDColor(unsigned int led, uint8_t red, uint8_t green, uint8_t blue); + void ApplyColors(); + + private: + #ifdef _WIN32 + HANDLE hDevice; + #else + + #endif + unsigned int led_count; + unsigned char active_mode; + unsigned char active_direction; + unsigned char active_speed; + + /*-----------------------------------------------------------------------------------*\ + | packet_[1-3] contain the data needed to be sent to the device, in sequential order. | + | These packets should initially contain the data in packet_[1-3]_template, which can | + | then have its bytes corresponding to color, speed, and direction updated via the | + | setter functions. Once the packets are ready, they can be sent via ApplyColors. | + \*-----------------------------------------------------------------------------------*/ + // pointer containing the first packet to be sent to the device + uint32_t* packet_one; + // pointer containing the second packet to be sent to the device + uint32_t* packet_two; + // pointer containing the third packet to be sent to the device + uint32_t* packet_three; + const uint32_t packet_one_template[59] = {0x00000001, 0x00000054, 0x00000003, 0x80000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000018, 0x00000000, + 0x00000001, 0x00000090, 0x000000D0, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x003000FB, 0x00000031, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000006, 0x00000000, 0x608100CE, 0x03100018, 0x51987856, 0x80000B00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // COLORS + 0x00000000}; + + const uint32_t packet_two_template[54] = {0x00000001, 0x00000054, 0x00000003, 0x80000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000004, 0x00000000, + 0x00000001, 0x00000090, 0x000000D0, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x003000FB, 0x00000031, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x208000CE, 0x03100004, 0x51987856, 0x80000B00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000100, 0x00000000}; + + const uint32_t packet_three_template[54] = {0x00000001, 0x00000054, 0x00000003, 0x80000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000004, 0x00000000, + 0x00000001, 0x00000090, 0x000000D0, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x003000FB, 0x00000031, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x2F8000CE, 0x01100001, 0x51987856, 0x80000B00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000000}; + + void InitializePackets(); +}; \ No newline at end of file diff --git a/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GControllerDetect.cpp b/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GControllerDetect.cpp new file mode 100644 index 000000000..beb2b0d58 --- /dev/null +++ b/Controllers/XPGSpectrixS40GController/XPGSpectrixS40GControllerDetect.cpp @@ -0,0 +1,82 @@ +/*-------------------------------------------------------------------*\ +| XPGSpectrixS40GControllerDetect.cpp | +| | +| Driver for XPG's Spectrix S40G NVMe | +| | +| NicolasNewman 25th Mar 2021 | +| | +\*-------------------------------------------------------------------*/ + +#include "Detector.h" +#include "XPGSpectrixS40GController.h" +#include "RGBController.h" +#include "RGBController_XPGSpectrixS40G.h" +#include +#include + +#ifdef _WIN32 + #define DEVBUFSIZE (128 * 1024) + #include + #include +#else + // TODO +#endif + +/******************************************************************************************\ +* * +* DetectXPGSpectrixS40GControllers * +* * +* Tests for the existance of a file descriptor matching * +* SCSI#Disk&Ven_NVMe&Prod_XPG_SPECTRIX_S40# on Windows machines * +* * +\******************************************************************************************/ + +#ifdef _WIN32 + int Search(wchar_t *dev_name) { + wchar_t buff[DEVBUFSIZE] = L""; + int wchar_count; + + wchar_count = QueryDosDeviceW(NULL, buff, DEVBUFSIZE); + if (wchar_count == 0) { + return 0; + } + for (int i = 0; i < wchar_count; i++) { + if (wcsstr(buff + i, L"SCSI#Disk&Ven_NVMe&Prod_XPG_SPECTRIX_S40#")) { + wcsncpy(dev_name, buff + i, MAX_PATH); + (dev_name)[MAX_PATH - 1] = '\0'; + return 1; + } + i += wcslen(buff + i); + } + return 0; + } +#else + int Search() { + return 0; + } +#endif /* Search() */ + + +void DetectSpectrixS40GControllers(std::vector& rgb_controllers) +{ + XPGSpectrixS40GController* new_xpg_s40g; + RGBController_XPGSpectrixS40G* new_controller; + #ifdef _WIN32 + // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-scsi-devices + wchar_t dev_name[MAX_PATH]; + if (Search(dev_name)) { + new_xpg_s40g = new XPGSpectrixS40GController(); + int result = new_xpg_s40g->SetHandle(dev_name); + if (result) { + new_controller = new RGBController_XPGSpectrixS40G(new_xpg_s40g); + rgb_controllers.push_back(new_controller); + } else { + delete new_xpg_s40g; + } + } + #else + // TODO + #endif +} /* DetectSpectrixS40GControllers() */ + +REGISTER_DETECTOR("XPG Spectrix S40G NVMe", DetectSpectrixS40GControllers); diff --git a/OpenRGB.pro b/OpenRGB.pro index 874c85e87..566fb28fc 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -142,6 +142,7 @@ INCLUDEPATH += Controllers/ThermaltakePoseidonZRGBController/ \ Controllers/ThermaltakeRiingController/ \ Controllers/WootingKeyboardController/ \ + Controllers/XPGSpectrixS40GController/ \ Controllers/YeelightController/ \ Controllers/ZalmanZSyncController/ \ RGBController/ \ @@ -463,6 +464,8 @@ HEADERS += Controllers/WootingKeyboardController/WootingTwoKeyboardController.h \ Controllers/WootingKeyboardController/RGBController_WootingKeyboard.h \ Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.h \ + Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.h \ + Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.h \ Controllers/YeelightController/YeelightController.h \ Controllers/YeelightController/RGBController_Yeelight.h \ Controllers/ZalmanZSyncController/ZalmanZSyncController.h \ @@ -878,6 +881,9 @@ SOURCES += Controllers/WootingKeyboardController/WootingTwoKeyboardController.cpp \ Controllers/WootingKeyboardController/RGBController_WootingKeyboard.cpp \ Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.cpp \ + Controllers/XPGSpectrixS40GController/XPGSpectrixS40GController.cpp \ + Controllers/XPGSpectrixS40GController/XPGSpectrixS40GControllerDetect.cpp \ + Controllers/XPGSpectrixS40GController/RGBController_XPGSpectrixS40G.cpp \ Controllers/YeelightController/YeelightController.cpp \ Controllers/YeelightController/YeelightControllerDetect.cpp \ Controllers/YeelightController/RGBController_Yeelight.cpp \ diff --git a/RGBController/RGBController.cpp b/RGBController/RGBController.cpp index 5f177a0eb..4cb9a7c47 100644 --- a/RGBController/RGBController.cpp +++ b/RGBController/RGBController.cpp @@ -1605,6 +1605,8 @@ std::string device_type_to_str(device_type type) return "Light"; case DEVICE_TYPE_SPEAKER: return "Speaker"; + case DEVICE_TYPE_STORAGE: + return "Storage"; case DEVICE_TYPE_VIRTUAL: return "Virtual"; default: diff --git a/RGBController/RGBController.h b/RGBController/RGBController.h index 28e4af03a..08410340c 100644 --- a/RGBController/RGBController.h +++ b/RGBController/RGBController.h @@ -131,6 +131,7 @@ enum DEVICE_TYPE_LIGHT, DEVICE_TYPE_SPEAKER, DEVICE_TYPE_VIRTUAL, + DEVICE_TYPE_STORAGE, DEVICE_TYPE_UNKNOWN }; diff --git a/qt/OpenRGBDialog2.cpp b/qt/OpenRGBDialog2.cpp index 063524c35..2c89c6828 100644 --- a/qt/OpenRGBDialog2.cpp +++ b/qt/OpenRGBDialog2.cpp @@ -73,6 +73,9 @@ static QString GetIconString(device_type type, bool dark) case DEVICE_TYPE_VIRTUAL: filename = "virtual"; break; + case DEVICE_TYPE_STORAGE: + filename = "storage"; + break; default: filename = "unknown"; break; diff --git a/qt/resources.qrc b/qt/resources.qrc index af368c380..ba8ec8c7c 100644 --- a/qt/resources.qrc +++ b/qt/resources.qrc @@ -46,5 +46,7 @@ wireless_dark.png console.png console_dark.png + storage.png + storage_dark.png diff --git a/qt/storage.png b/qt/storage.png new file mode 100644 index 0000000000000000000000000000000000000000..e61a83db3c758db311250ca965d20ac184284227 GIT binary patch literal 2930 zcmcIm-HY5*6i-2renJm5pQm8cH_?E#w4>d zTLh~`u@6s~BGE!ijw`$KAFmz1MK>eQ+EYZZH^n+)(tV4r3vrQX+J0lKYjU?!251V*jud0wXjTQ z{E7V$-MxQTgY2IrwkvFVj34PDFwmk2=DV$C5TkBM=-EZ^oeoO^-&09uOTuXCke{ke z@?{oL-YCc-k>w(9+6BeXi?+O#S7lX}6jhRKQBhFQM7qxRF9Ezou7~QC?R{VHR}yBD zBt(+b>2wMmt-zvbNwIBPl2u7nMbHrA`5?hvF^IPeEL3PrB0o%g7VxP>?67uH5&&ry zLMzP825~=4kT9u>LrE#fX-GXqm*je3J8JfvyF{W*+M+=cgRYY6hBGW-@eEtWbS_@x z08(44;9B^lHkVRfq3kv`6UO#YICw?T2p+A9Ea6(H0 z5J?ebRaC8pq9WBmswT=sB+Hp3=v}N!L8L$HHZ@& z5L&I21ci$rt`A`br}I0 z3-C;X6fNp_qH9@}DBEDovW=o>8kXlNimDlgI zrZ4ornm*qvLWD^MpQIF~uFxO$msrHrr7JVrnW2!V>rgvWiDu%*TC`LzSS<%(=S9%I^M?NKT5sl`{nr+rvZfdK z&~a)o1ZTALGd~={Pky|l0aR)PhsSddeD)?BJm0ETMjO`QqxI2^2jsQ0-@kqJrBhdq zZ*|Xp^UxFb96MIuUgfwWmp)uqz2yKodHTW^7xs+&c;xaO2fo|1;q<{Dgw2QE{dyn3M z?clF()q{^-dE@cT&mOCNe(va%OQ%L&{NwnZGi!do9gQCM?|vse6<5c1RX!bi?v=j* D-0iQU literal 0 HcmV?d00001 diff --git a/qt/storage_dark.png b/qt/storage_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5bb9937ba7322db32a9f91c2a6faf3bda4a13c93 GIT binary patch literal 2915 zcmcImU1%It6y6H08XHmTLlvRJw4$cY&i}7nL%N$b+qyL*D@`njckjKs8L~5XoS9@d zm4X%@EZ8TJYVlQkQ41ozsMtO!+9zL&;6p**8t~^y&~tZoC!3lyvDSh4yXV|Fntfb$ogeyF?s+Ryfr4z(7D#By@vzn0Vci*t6@wHy@Top{J5Amc$9}P?)Pt3uP8l z!73^eRuogP-J)t4rmH+HXo{xDswOM0q^h22dxjzOFA==Or0LC6j`V%OUrAg@)5w$M zPN!4s=tUN{WYu+DSBl@r7+n)uu!21j{PY0StxLesKJ)fk_bq%5P~Q- z8zz04fH1j>B3UgeJfxl?!MR?v6t{cM36^P_1~g0)&{cEYXo00HSzw!(&c*8-0JXJR z?qfqNL6Eyh(#d5Aqff|&+DUySqVfz)*iww?5^i4ijt|;81b7c!>Szd{nx~JOfR3VEAO3{|e1ba;u2ME@{4^WHB zQP>iNd}X~dYqJ;}13G zJ%ls(n5Qr$Vt?4*U=g=RS7x@eK!K=Rq;{s3ux8ppF`Z}uyIYoyyczfeE#DftfgJ}M ziXk1@2o9NiE4Q!L9xoI#r_l^HK7|g$k79^q@#+i1Owdck&c5O!V<+IQa2|6S|N{Imbs!g<#80v|d~4Tj*1 z#y|7JA^haWOBzC@#&CFiF(n_u!SnTMWuoq!|6umi$ZN{(#mV39ddYd>(zy8encD8R z&Rf@hNN4r8@4nG^a7_HPb!F$57lQeRE?=1_TsScH&au^zcdxo1KioaLZ