Add XPG Spectrix S40G ENE interface for Windows
This commit is contained in:
parent
af43171066
commit
41f75d958c
4 changed files with 403 additions and 0 deletions
|
|
@ -0,0 +1,248 @@
|
|||
/*-----------------------------------------*\
|
||||
| ENESMBusInterface_SpectrixS40G_Windows |
|
||||
| |
|
||||
| Code for ENE XPG Spectrix S40G NVMe |
|
||||
| interface |
|
||||
| Windows implementation |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 11/21/2021 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "ENESMBusInterface_SpectrixS40G_Windows.h"
|
||||
|
||||
#include <fileapi.h>
|
||||
#include <winioctl.h>
|
||||
#include <nvme.h>
|
||||
|
||||
ENESMBusInterface_SpectrixS40G::ENESMBusInterface_SpectrixS40G(HANDLE fd, wchar_t* path)
|
||||
{
|
||||
this->nvme_fd = fd;
|
||||
this->path = path;
|
||||
}
|
||||
|
||||
std::string ENESMBusInterface_SpectrixS40G::GetLocation()
|
||||
{
|
||||
std::string str(path.begin(), path.end());
|
||||
return("NVMe: " + str);
|
||||
}
|
||||
|
||||
int ENESMBusInterface_SpectrixS40G::GetMaxBlock()
|
||||
{
|
||||
return(24);
|
||||
}
|
||||
|
||||
unsigned char ENESMBusInterface_SpectrixS40G::ENERegisterRead(ene_dev_id dev, ene_register reg)
|
||||
{
|
||||
if(nvme_fd != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create buffer to hold STORAGE_PROTOCOL_COMMAND |
|
||||
| Size must be enough for the STORAGE_PROTOCOL_COMMAND struct plus the command |
|
||||
| data. Subtract sizeof(DWORD) as the Command field in the structure overlaps |
|
||||
| the actual command data. |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
unsigned char buffer[sizeof(STORAGE_PROTOCOL_COMMAND) + (sizeof(DWORD) * 34) - sizeof(DWORD)] = {0};
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create STORAGE_PROTOCOL_COMMAND pointer and point it to the buffer |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
PSTORAGE_PROTOCOL_COMMAND command = (PSTORAGE_PROTOCOL_COMMAND)buffer;
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Fill in STORAGE_PROTOCOL_COMMAND structure |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
command->Version = STORAGE_PROTOCOL_STRUCTURE_VERSION;
|
||||
command->Length = sizeof(STORAGE_PROTOCOL_COMMAND);
|
||||
command->ProtocolType = ProtocolTypeNvme;
|
||||
command->Flags = STORAGE_PROTOCOL_COMMAND_FLAG_ADAPTER_REQUEST;
|
||||
command->ReturnStatus = 0x00000000;
|
||||
command->ErrorCode = 0x00000000;
|
||||
command->CommandLength = STORAGE_PROTOCOL_COMMAND_LENGTH_NVME;
|
||||
command->ErrorInfoLength = 0x00000040;
|
||||
command->DataToDeviceTransferLength = 0x00000000;
|
||||
command->DataFromDeviceTransferLength = 0x00000001;
|
||||
command->TimeOutValue = 0x00000001;
|
||||
command->ErrorInfoOffset = 0x00000090;
|
||||
command->DataToDeviceBufferOffset = 0x00000000;
|
||||
command->DataFromDeviceBufferOffset = 0x000000D0;
|
||||
command->CommandSpecific = STORAGE_PROTOCOL_SPECIFIC_NVME_ADMIN_COMMAND;
|
||||
command->Reserved0 = 0x00000000;
|
||||
command->FixedProtocolReturnData = 0x00000000;
|
||||
command->Reserved1[0] = 0x00000000;
|
||||
command->Reserved1[1] = 0x00000000;
|
||||
command->Reserved1[2] = 0x00000000;
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create ENE Register Write command, filling in the appropriate register and |
|
||||
| value |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
PNVME_COMMAND CommandValue = (PNVME_COMMAND)command->Command;
|
||||
|
||||
unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF);
|
||||
|
||||
CommandValue->CDW0.OPC = 0xFA;
|
||||
CommandValue->u.GENERAL.CDW12 = (corrected_reg << 16) | (dev << 1);
|
||||
CommandValue->u.GENERAL.CDW13 = 0x81100001;
|
||||
|
||||
DWORD ExtraValue[18] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Send the STORAGE_PROTOCOL_COMMAND to the device |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
DWORD bytesreturned = 0;
|
||||
bool result = DeviceIoControl(nvme_fd, IOCTL_STORAGE_PROTOCOL_COMMAND, buffer, sizeof(buffer), buffer, sizeof(buffer), &bytesreturned, (LPOVERLAPPED)0x0);
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Copy the ENE Register Write extra data into the STORAGE_PROTOCOL_COMMAND |
|
||||
| buffer |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
memcpy(ExtraValue, &command->Command + sizeof(NVME_COMMAND), sizeof(ExtraValue));
|
||||
|
||||
return(ExtraValue[16]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ENESMBusInterface_SpectrixS40G::ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val)
|
||||
{
|
||||
if(nvme_fd != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create buffer to hold STORAGE_PROTOCOL_COMMAND |
|
||||
| Size must be enough for the STORAGE_PROTOCOL_COMMAND struct plus the command |
|
||||
| data. Subtract sizeof(DWORD) as the Command field in the structure overlaps |
|
||||
| the actual command data. |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
unsigned char buffer[sizeof(STORAGE_PROTOCOL_COMMAND) + (sizeof(DWORD) * 34) - sizeof(DWORD)];
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create STORAGE_PROTOCOL_COMMAND pointer and point it to the buffer |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
PSTORAGE_PROTOCOL_COMMAND command = (PSTORAGE_PROTOCOL_COMMAND)buffer;
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Fill in STORAGE_PROTOCOL_COMMAND structure |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
command->Version = STORAGE_PROTOCOL_STRUCTURE_VERSION;
|
||||
command->Length = sizeof(STORAGE_PROTOCOL_COMMAND);
|
||||
command->ProtocolType = ProtocolTypeNvme;
|
||||
command->Flags = STORAGE_PROTOCOL_COMMAND_FLAG_ADAPTER_REQUEST;
|
||||
command->ReturnStatus = 0x00000000;
|
||||
command->ErrorCode = 0x00000000;
|
||||
command->CommandLength = STORAGE_PROTOCOL_COMMAND_LENGTH_NVME;
|
||||
command->ErrorInfoLength = 0x00000040;
|
||||
command->DataToDeviceTransferLength = 0x00000001;
|
||||
command->DataFromDeviceTransferLength = 0x00000000;
|
||||
command->TimeOutValue = 0x00000001;
|
||||
command->ErrorInfoOffset = 0x00000090;
|
||||
command->DataToDeviceBufferOffset = 0x000000D0;
|
||||
command->DataFromDeviceBufferOffset = 0x00000000;
|
||||
command->CommandSpecific = STORAGE_PROTOCOL_SPECIFIC_NVME_ADMIN_COMMAND;
|
||||
command->Reserved0 = 0x00000000;
|
||||
command->FixedProtocolReturnData = 0x00000000;
|
||||
command->Reserved1[0] = 0x00000000;
|
||||
command->Reserved1[1] = 0x00000000;
|
||||
command->Reserved1[2] = 0x00000000;
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create ENE Register Write command, filling in the appropriate register and |
|
||||
| value |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
PNVME_COMMAND CommandValue = (PNVME_COMMAND)command->Command;
|
||||
|
||||
unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF);
|
||||
|
||||
CommandValue->CDW0.OPC = 0xFB;
|
||||
CommandValue->u.GENERAL.CDW12 = (corrected_reg << 16) | (dev << 1);
|
||||
CommandValue->u.GENERAL.CDW13 = 0x01100001;
|
||||
|
||||
DWORD ExtraValue[18] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
|
||||
|
||||
ExtraValue[16] = val;
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Copy the ENE Register Write extra data into the STORAGE_PROTOCOL_COMMAND |
|
||||
| buffer |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
memcpy(&command->Command + sizeof(NVME_COMMAND), ExtraValue, sizeof(ExtraValue));
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Send the STORAGE_PROTOCOL_COMMAND to the device |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
DeviceIoControl(nvme_fd, IOCTL_STORAGE_PROTOCOL_COMMAND, buffer, sizeof(buffer), buffer, sizeof(buffer), 0x0, (LPOVERLAPPED)0x0);
|
||||
}
|
||||
}
|
||||
|
||||
void ENESMBusInterface_SpectrixS40G::ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz)
|
||||
{
|
||||
if(nvme_fd != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create buffer to hold STORAGE_PROTOCOL_COMMAND |
|
||||
| Size must be enough for the STORAGE_PROTOCOL_COMMAND struct plus the command |
|
||||
| data. Subtract sizeof(DWORD) as the Command field in the structure overlaps |
|
||||
| the actual command data. |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
unsigned char buffer[sizeof(STORAGE_PROTOCOL_COMMAND) + (sizeof(DWORD) * 39) - sizeof(DWORD)];
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create STORAGE_PROTOCOL_COMMAND pointer and point it to the buffer |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
PSTORAGE_PROTOCOL_COMMAND command = (PSTORAGE_PROTOCOL_COMMAND)buffer;
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Fill in STORAGE_PROTOCOL_COMMAND structure |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
command->Version = STORAGE_PROTOCOL_STRUCTURE_VERSION;
|
||||
command->Length = sizeof(STORAGE_PROTOCOL_COMMAND);
|
||||
command->ProtocolType = ProtocolTypeNvme;
|
||||
command->Flags = STORAGE_PROTOCOL_COMMAND_FLAG_ADAPTER_REQUEST;
|
||||
command->ReturnStatus = 0x00000000;
|
||||
command->ErrorCode = 0x00000000;
|
||||
command->CommandLength = STORAGE_PROTOCOL_COMMAND_LENGTH_NVME;
|
||||
command->ErrorInfoLength = 0x00000040;
|
||||
command->DataToDeviceTransferLength = sz;
|
||||
command->DataFromDeviceTransferLength = 0x00000000;
|
||||
command->TimeOutValue = 0x00000001;
|
||||
command->ErrorInfoOffset = 0x00000090;
|
||||
command->DataToDeviceBufferOffset = 0x000000D0;
|
||||
command->DataFromDeviceBufferOffset = 0x00000000;
|
||||
command->CommandSpecific = STORAGE_PROTOCOL_SPECIFIC_NVME_ADMIN_COMMAND;
|
||||
command->Reserved0 = 0x00000000;
|
||||
command->FixedProtocolReturnData = 0x00000000;
|
||||
command->Reserved1[0] = 0x00000000;
|
||||
command->Reserved1[1] = 0x00000000;
|
||||
command->Reserved1[2] = 0x00000000;
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Create ENE Register Write Block command, filling in the appropriate register |
|
||||
| and value |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
PNVME_COMMAND CommandValue = (PNVME_COMMAND)command->Command;
|
||||
|
||||
unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF);
|
||||
|
||||
CommandValue->CDW0.OPC = 0xFB;
|
||||
CommandValue->u.GENERAL.CDW12 = (corrected_reg << 16) | (dev << 1);
|
||||
CommandValue->u.GENERAL.CDW13 = 0x03100000 | sz;
|
||||
|
||||
DWORD ExtraValue[23] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000 };
|
||||
|
||||
memcpy(&ExtraValue[16], data, sz);
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Copy the ENE Register Write Block extra data into the |
|
||||
| STORAGE_PROTOCOL_COMMAND buffer |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
memcpy(&command->Command + sizeof(NVME_COMMAND), ExtraValue, sizeof(ExtraValue));
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Send the STORAGE_PROTOCOL_COMMAND to the device |
|
||||
\*-----------------------------------------------------------------------------*/
|
||||
DeviceIoControl(nvme_fd, IOCTL_STORAGE_PROTOCOL_COMMAND, buffer, sizeof(buffer), buffer, sizeof(buffer), 0x0, (LPOVERLAPPED)0x0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*-----------------------------------------*\
|
||||
| ENESMBusInterface_SpectrixS40G_Windows.h |
|
||||
| |
|
||||
| Definitions and types for ENE XPG |
|
||||
| Spectrix S40G NVMe interface |
|
||||
| Windows implementation |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 11/21/2021 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "ENESMBusInterface.h"
|
||||
#include <windows.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
class ENESMBusInterface_SpectrixS40G : public ENESMBusInterface
|
||||
{
|
||||
public:
|
||||
ENESMBusInterface_SpectrixS40G(HANDLE fd, wchar_t* path);
|
||||
|
||||
std::string GetLocation();
|
||||
int GetMaxBlock();
|
||||
unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg);
|
||||
void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val);
|
||||
void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz);
|
||||
|
||||
private:
|
||||
HANDLE nvme_fd;
|
||||
std::wstring path;
|
||||
};
|
||||
122
Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp
Normal file
122
Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
#include "Detector.h"
|
||||
#include "ENESMBusController.h"
|
||||
#include "ENESMBusInterface_SpectrixS40G_Windows.h"
|
||||
#include "LogManager.h"
|
||||
#include "RGBController.h"
|
||||
#include "RGBController_ENESMBus.h"
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DEVBUFSIZE (128 * 1024)
|
||||
#include <windows.h>
|
||||
#include <fileapi.h>
|
||||
|
||||
/*----------------------------------------------------------------------*\
|
||||
| Windows defines "interface" for some reason. Work around this |
|
||||
\*----------------------------------------------------------------------*/
|
||||
#ifdef interface
|
||||
#undef interface
|
||||
#endif
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* Search *
|
||||
* *
|
||||
* Search for an NVMe device matching "XPG SPECTRIX S40G" *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* OpenDevice *
|
||||
* *
|
||||
* Open a handle to the given device path *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
HANDLE OpenDevice(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);
|
||||
|
||||
HANDLE hDevice = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)0x0, OPEN_EXISTING, 0x0, (HANDLE)0x0);
|
||||
|
||||
return(hDevice);
|
||||
}
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* DetectSpectrixS40GControllers *
|
||||
* *
|
||||
* Detects ENE SMBus controllers on XPG Spectrix S40G NVMe devices *
|
||||
* *
|
||||
* Tests for the existance of a file descriptor matching *
|
||||
* SCSI#Disk&Ven_NVMe&Prod_XPG_SPECTRIX_S40# on Windows machines *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
void DetectSpectrixS40GControllers(std::vector<RGBController*>& rgb_controllers)
|
||||
{
|
||||
/*-------------------------------------------------------------------------------------------------*\
|
||||
| https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-scsi-devices |
|
||||
\*-------------------------------------------------------------------------------------------------*/
|
||||
wchar_t dev_name[MAX_PATH];
|
||||
|
||||
if(Search(dev_name))
|
||||
{
|
||||
HANDLE nvme_fd = OpenDevice(dev_name);
|
||||
|
||||
if(nvme_fd != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ENESMBusInterface_SpectrixS40G* interface = new ENESMBusInterface_SpectrixS40G(nvme_fd, dev_name);
|
||||
ENESMBusController* controller = new ENESMBusController(interface, 0x67);
|
||||
RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller);
|
||||
|
||||
rgb_controller->name = "XPG Spectrix S40G";
|
||||
rgb_controller->type = DEVICE_TYPE_STORAGE;
|
||||
rgb_controller->vendor = "XPG";
|
||||
|
||||
rgb_controllers.push_back(rgb_controller);
|
||||
}
|
||||
}
|
||||
} /* DetectSpectrixS40GControllers() */
|
||||
|
||||
|
||||
REGISTER_DETECTOR( "XPG Spectrix S40G", DetectSpectrixS40GControllers);
|
||||
|
|
@ -1040,6 +1040,8 @@ win32:SOURCES +=
|
|||
AutoStart/AutoStart-Windows.cpp \
|
||||
Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp \
|
||||
Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp \
|
||||
Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp \
|
||||
Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.cpp \
|
||||
Controllers/OpenRazerController/OpenRazerWindowsDetect.cpp \
|
||||
Controllers/OpenRazerController/RGBController_OpenRazerWindows.cpp \
|
||||
|
||||
|
|
@ -1057,6 +1059,7 @@ win32:HEADERS +=
|
|||
wmi/acpiwmi.h \
|
||||
AutoStart/AutoStart-Windows.h \
|
||||
Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h \
|
||||
Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.h \
|
||||
Controllers/OpenRazerController/RGBController_OpenRazerWindows.h \
|
||||
|
||||
win32:contains(QMAKE_TARGET.arch, x86_64) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue