Replace WinRing0 with PawnIO for SMBus and Super-IO access on Windows

Commits squashed, files cleaned up, and rebased by Adam Honse <calcprogrammer1@gmail.com>
This commit is contained in:
Stephen Horvath
2025-05-13 02:33:05 +10:00
committed by Adam Honse
parent 66c9691c87
commit 977269dfe6
35 changed files with 1140 additions and 1067 deletions

View File

@@ -198,7 +198,6 @@ HEADERS +=
serial_port/find_usb_serial_port.h \
serial_port/serial_port.h \
StringUtils.h \
super_io/super_io.h \
SuspendResume/SuspendResume.h \
AutoStart/AutoStart.h \
KeyboardLayoutManager/KeyboardLayoutManager.h \
@@ -265,7 +264,6 @@ SOURCES +=
net_port/net_port.cpp \
serial_port/serial_port.cpp \
StringUtils.cpp \
super_io/super_io.cpp \
AutoStart/AutoStart.cpp \
KeyboardLayoutManager/KeyboardLayoutManager.cpp \
RGBController/RGBController.cpp \
@@ -329,10 +327,11 @@ win32:QMAKE_CXXFLAGS += /utf-8
win32:INCLUDEPATH += \
dependencies/display-library/include \
dependencies/hidapi-win/include \
dependencies/winring0/include \
dependencies/libusb-1.0.27/include \
dependencies/mbedtls-3.2.1/include \
dependencies/NVFC \
dependencies/PawnIO \
i2c_smbus/Windows \
wmi/ \
win32:SOURCES += $$CONTROLLER_CPP_WINDOWS
@@ -340,11 +339,10 @@ win32:SOURCES += $$CONTROLLER_CPP_WINDOWS
win32:SOURCES += \
dependencies/hueplusplus-1.2.0/src/WinHttpHandler.cpp \
dependencies/NVFC/nvapi.cpp \
i2c_smbus/i2c_smbus_amdadl.cpp \
i2c_smbus/i2c_smbus_i801.cpp \
i2c_smbus/i2c_smbus_nct6775.cpp \
i2c_smbus/i2c_smbus_nvapi.cpp \
i2c_smbus/i2c_smbus_piix4.cpp \
i2c_smbus/Windows/i2c_smbus_amdadl.cpp \
i2c_smbus/Windows/i2c_smbus_nvapi.cpp \
i2c_smbus/Windows/i2c_smbus_pawnio.cpp \
super_io/super_io_pawnio.cpp \
scsiapi/scsiapi_windows.c \
serial_port/find_usb_serial_port_win.cpp \
SuspendResume/SuspendResume_Windows.cpp \
@@ -358,12 +356,12 @@ win32:HEADERS +=
dependencies/display-library/include/adl_defines.h \
dependencies/display-library/include/adl_sdk.h \
dependencies/display-library/include/adl_structures.h \
dependencies/winring0/include/OlsApi.h \
dependencies/NVFC/nvapi.h \
i2c_smbus/i2c_smbus_i801.h \
i2c_smbus/i2c_smbus_nct6775.h \
i2c_smbus/i2c_smbus_nvapi.h \
i2c_smbus/i2c_smbus_piix4.h \
dependencies/PawnIO/PawnIOLib.h \
i2c_smbus/Windows/i2c_smbus_amdadl.h \
i2c_smbus/Windows/i2c_smbus_nvapi.h \
i2c_smbus/Windows/i2c_smbus_pawnio.h \
super_io/super_io_pawnio.h \
wmi/wmi.h \
AutoStart/AutoStart-Windows.h \
SuspendResume/SuspendResume_Windows.h \
@@ -372,17 +370,16 @@ win32:contains(QMAKE_TARGET.arch, x86_64) {
LIBS += \
-lws2_32 \
-liphlpapi \
-L"$$PWD/dependencies/winring0/x64/" -lWinRing0x64 \
-L"$$PWD/dependencies/libusb-1.0.27/VS2019/MS64/dll" -llibusb-1.0 \
-L"$$PWD/dependencies/hidapi-win/x64/" -lhidapi \
-L"$$PWD/dependencies/mbedtls-3.2.1/lib/x64/" -lmbedcrypto -lmbedtls -lmbedx509 \
-L"$$PWD/dependencies/PawnIO/" -lPawnIOLib \
}
win32:contains(QMAKE_TARGET.arch, x86) {
LIBS += \
-lws2_32 \
-liphlpapi \
-L"$$PWD/dependencies/winring0/Win32/" -lWinRing0 \
-L"$$PWD/dependencies/libusb-1.0.27/VS2019/MS32/dll" -llibusb-1.0 \
-L"$$PWD/dependencies/hidapi-win/x86/" -lhidapi \
-L"$$PWD/dependencies/mbedtls-3.2.1/lib/x86/" -lmbedcrypto -lmbedtls -lmbedx509 \
@@ -402,6 +399,11 @@ win32:DEFINES +=
win32:RC_ICONS += \
qt/OpenRGB.ico
win32:DISTFILES += \
dependencies/PawnIO/modules/SmbusPIIX4.bin \
dependencies/PawnIO/modules/SmbusI801.bin \
dependencies/PawnIO/modules/LpcIO.bin
#-----------------------------------------------------------------------------------------------#
# Windows GitLab CI Configuration #
#-----------------------------------------------------------------------------------------------#
@@ -423,10 +425,12 @@ win32:UI_DIR = _intermediate_$$DESTDIR/.ui
#-----------------------------------------------------------------------------------------------#
win32:contains(QMAKE_TARGET.arch, x86_64) {
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/libusb-1.0.27/VS2019/MS64/dll/libusb-1.0.dll)\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/hidapi-win/x64/hidapi.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/PawnIOLib.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/SmbusPIIX4.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/SmbusI801.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/PawnIO/modules/LpcIO.bin )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
first.depends = $(first) copydata
export(first.depends)
export(copydata.commands)
@@ -434,9 +438,6 @@ win32:contains(QMAKE_TARGET.arch, x86_64) {
}
win32:contains(QMAKE_TARGET.arch, x86) {
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/Win32/WinRing0.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/Win32/WinRing0.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/libusb-1.0.27/VS2019/MS32/dll/libusb-1.0.dll)\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/hidapi-win/x86/hidapi.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t)
@@ -461,14 +462,16 @@ contains(QMAKE_PLATFORM, linux) {
HEADERS += \
dependencies/NVFC/nvapi.h \
i2c_smbus/i2c_smbus_linux.h \
i2c_smbus/Linux/i2c_smbus_linux.h \
AutoStart/AutoStart-Linux.h \
SPDAccessor/EE1004Accessor_Linux.h \
SPDAccessor/SPD5118Accessor_Linux.h \
SuspendResume/SuspendResume_Linux_FreeBSD.h \
super_io/super_io.h \
INCLUDEPATH += \
dependencies/NVFC \
i2c_smbus/Linux \
/usr/include/mbedtls/ \
LIBS += \
@@ -515,7 +518,7 @@ contains(QMAKE_PLATFORM, linux) {
SOURCES += \
dependencies/hueplusplus-1.2.0/src/LinHttpHandler.cpp \
dependencies/NVFC/nvapi.cpp \
i2c_smbus/i2c_smbus_linux.cpp \
i2c_smbus/Linux/i2c_smbus_linux.cpp \
scsiapi/scsiapi_linux.c \
serial_port/find_usb_serial_port_linux.cpp \
AutoStart/AutoStart-Linux.cpp \
@@ -523,6 +526,7 @@ contains(QMAKE_PLATFORM, linux) {
SPDAccessor/SPD5118Accessor_Linux.cpp \
SuspendResume/SuspendResume_Linux_FreeBSD.cpp \
startup/main_Linux_MacOS.cpp \
super_io/super_io.cpp \
#-------------------------------------------------------------------------------------------#
# Set up install paths #
@@ -598,6 +602,7 @@ contains(QMAKE_PLATFORM, freebsd) {
HEADERS += \
AutoStart/AutoStart-FreeBSD.h \
SuspendResume/SuspendResume_Linux_FreeBSD.h \
super_io/super_io.h \
HEADERS -= \
Controllers/SeagateController/RGBController_Seagate.h \
@@ -646,6 +651,7 @@ contains(QMAKE_PLATFORM, freebsd) {
serial_port/find_usb_serial_port_linux.cpp \
AutoStart/AutoStart-FreeBSD.cpp \
SuspendResume/SuspendResume_Linux_FreeBSD.cpp \
super_io/super_io.cpp \
SOURCES -= \
Controllers/SeagateController/RGBController_Seagate.cpp \
@@ -748,6 +754,10 @@ macx:contains(QMAKE_HOST.arch, arm64) {
SOURCES += \
scsiapi/scsiapi_macos.c \
super_io/super_io.cpp \
HEADERS += \
super_io/super_io.h \
LIBS += \
-L/opt/homebrew/lib \
@@ -759,20 +769,23 @@ macx:contains(QMAKE_HOST.arch, arm64) {
macx:contains(QMAKE_HOST.arch, x86_64) {
INCLUDEPATH += \
dependencies/macUSPCIO \
i2c_smbus/MacOS \
/usr/local/include \
/usr/local/homebrew/include \
SOURCES += \
i2c_smbus/i2c_smbus_i801.cpp \
i2c_smbus/i2c_smbus_nct6775.cpp \
i2c_smbus/i2c_smbus_piix4.cpp \
i2c_smbus/MacOS/i2c_smbus_i801.cpp \
i2c_smbus/MacOS/i2c_smbus_nct6775.cpp \
i2c_smbus/MacOS/i2c_smbus_piix4.cpp \
scsiapi/scsiapi_macos.c \
super_io/super_io.cpp \
HEADERS += \
dependencies/macUSPCIO/macUSPCIOAccess.h \
i2c_smbus/i2c_smbus_i801.h \
i2c_smbus/i2c_smbus_nct6775.h \
i2c_smbus/i2c_smbus_piix4.h \
i2c_smbus/MacOS/i2c_smbus_i801.h \
i2c_smbus/MacOS/i2c_smbus_nct6775.h \
i2c_smbus/MacOS/i2c_smbus_piix4.h \
super_io/super_io.h \
LIBS += \
-L/usr/local/lib \

View File

@@ -132,8 +132,7 @@ This project interacts directly with hardware using reverse engineered protocols
## Projects Used
* OpenRGB directly relies upon these projects.
* WinRing0: https://openlibsys.org/
* PawnIO: https://pawnio.eu/
* libusb: https://github.com/libusb/libusb
* hidapi: https://github.com/libusb/hidapi
* libe131: https://github.com/hhromic/libe131

BIN
dependencies/PawnIO/PawnIOLib.dll vendored Normal file
View File

Binary file not shown.

75
dependencies/PawnIO/PawnIOLib.h vendored Normal file
View File

@@ -0,0 +1,75 @@
// PawnIOLib - Library and tooling source to be used with PawnIO.
// Copyright (C) 2023 namazso <admin@namazso.eu>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef PAWNIOLIB_LIBRARY_H
#define PAWNIOLIB_LIBRARY_H
#ifdef PawnIOLib_EXPORTS
#define PAWNIO_EXPORT __declspec(dllexport)
#else
#define PAWNIO_EXPORT __declspec(dllimport)
#endif
#define PAWNIOAPI EXTERN_C PAWNIO_EXPORT HRESULT STDAPICALLTYPE
/// Get PawnIOLib version.
///
/// @p version A pointer to a ULONG which receives the version.
/// @return A HRESULT.
PAWNIOAPI pawnio_version(PULONG version);
/// Open a PawnIO executor.
///
/// @p handle A handle to the executor, or NULL.
/// @return A HRESULT.
PAWNIOAPI pawnio_open(PHANDLE handle);
/// Load a PawnIO blob.
///
/// @p handle Handle from @c pawnio_open.
/// @p blob Blob to load.
/// @p size Size of blob.
/// @return A HRESULT.
PAWNIOAPI pawnio_load(HANDLE handle, const UCHAR* blob, SIZE_T size);
/// Executes a function from the loaded blob.
///
/// @p handle Handle from @c pawnio_open.
/// @p name Function name to execute.
/// @p in Input buffer.
/// @p in_size Input buffer count.
/// @p out Output buffer.
/// @p out_size Output buffer count.
/// @p return_size Entries written in out_size.
/// @return A HRESULT.
PAWNIOAPI pawnio_execute(
HANDLE handle,
PCSTR name,
const ULONG64* in,
SIZE_T in_size,
PULONG64 out,
SIZE_T out_size,
PSIZE_T return_size
);
/// Close a PawnIO executor.
///
/// @p handle Handle from @c pawnio_open.
/// @return A HRESULT.
PAWNIOAPI pawnio_close(HANDLE handle);
#endif //PAWNIOLIB_LIBRARY_H

BIN
dependencies/PawnIO/PawnIOLib.lib vendored Normal file
View File

Binary file not shown.

BIN
dependencies/PawnIO/modules/LpcIO.bin vendored Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -1,580 +0,0 @@
//-----------------------------------------------------------------------------
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : http://openlibsys.org/
// License : The modified BSD license
//
// Copyright 2007-2009 OpenLibSys.org. All rights reserved.
//-----------------------------------------------------------------------------
// for WinRing0 1.3.x
#pragma once
/******************************************************************************
**
** DLL Information
**
******************************************************************************/
//-----------------------------------------------------------------------------
// GetDllStatus
//-----------------------------------------------------------------------------
DWORD // DLL Status, defined OLS_DLL_****
WINAPI GetDllStatus();
//-----------------------------------------------------------------------------
// GetDllVersion
//-----------------------------------------------------------------------------
DWORD // DLL Version, defined OLS_VERSION
WINAPI GetDllVersion(
PBYTE major, // major version
PBYTE minor, // minor version
PBYTE revision, // revision
PBYTE release // release/build
);
//-----------------------------------------------------------------------------
// GetDriverVersion
//-----------------------------------------------------------------------------
DWORD // Device Driver Version, defined OLS_DRIVER_VERSION
WINAPI GetDriverVersion(
PBYTE major, // major version
PBYTE minor, // minor version
PBYTE revision, // revision
PBYTE release // release/build
);
//-----------------------------------------------------------------------------
// GetDriverType
//-----------------------------------------------------------------------------
DWORD // Device Driver Type, defined OLS_DRIVER_TYPE_****
WINAPI GetDriverType();
//-----------------------------------------------------------------------------
// InitializeOls
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI InitializeOls();
//-----------------------------------------------------------------------------
// DeinitializeOls
//-----------------------------------------------------------------------------
VOID WINAPI DeinitializeOls();
/******************************************************************************
**
** CPU
**
******************************************************************************/
//-----------------------------------------------------------------------------
// IsCpuid
//-----------------------------------------------------------------------------
BOOL // TRUE: support CPUID instruction, FALSE: not support CPUID instruction
WINAPI IsCpuid();
//-----------------------------------------------------------------------------
// IsMsr
//-----------------------------------------------------------------------------
BOOL // TRUE: support MSR(Model-Specific Register), FALSE: not support MSR
WINAPI IsMsr();
//-----------------------------------------------------------------------------
// IsTsc
//-----------------------------------------------------------------------------
BOOL // TRUE: support TSC(Time Stamp Counter), FALSE: not support TSC
WINAPI IsTsc();
//-----------------------------------------------------------------------------
// Rdmsr
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI Rdmsr(
DWORD index, // MSR index
PDWORD eax, // bit 0-31
PDWORD edx // bit 32-63
);
//-----------------------------------------------------------------------------
// RdmsrTx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI RdmsrTx(
DWORD index, // MSR index
PDWORD eax, // bit 0-31
PDWORD edx, // bit 32-63
DWORD_PTR threadAffinityMask
);
//-----------------------------------------------------------------------------
// RdmsrPx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI RdmsrPx(
DWORD index, // MSR index
PDWORD eax, // bit 0-31
PDWORD edx, // bit 32-63
DWORD_PTR processAffinityMask
);
//-----------------------------------------------------------------------------
// Wrmsr
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI Wrmsr(
DWORD index, // MSR index
DWORD eax, // bit 0-31
DWORD edx // bit 32-63
);
//-----------------------------------------------------------------------------
// WrmsrTx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WrmsrTx(
DWORD index, // MSR index
DWORD eax, // bit 0-31
DWORD edx, // bit 32-63
DWORD_PTR threadAffinityMask
);
//-----------------------------------------------------------------------------
// WrmsrPx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WrmsrPx(
DWORD index, // MSR index
DWORD eax, // bit 0-31
DWORD edx, // bit 32-63
DWORD_PTR processAffinityMask
);
//-----------------------------------------------------------------------------
// Rdpmc
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI Rdpmc(
DWORD index, // PMC index
PDWORD eax, // bit 0-31
PDWORD edx // bit 32-63
);
//-----------------------------------------------------------------------------
// RdmsrTx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI RdpmcTx(
DWORD index, // PMC index
PDWORD eax, // bit 0-31
PDWORD edx, // bit 32-63
DWORD_PTR threadAffinityMask
);
//-----------------------------------------------------------------------------
// RdmsrPx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI RdpmcPx(
DWORD index, // PMC index
PDWORD eax, // bit 0-31
PDWORD edx, // bit 32-63
DWORD_PTR processAffinityMask
);
//-----------------------------------------------------------------------------
// Cpuid
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI Cpuid(
DWORD index, // CPUID index
PDWORD eax,
PDWORD ebx,
PDWORD ecx,
PDWORD edx
);
//-----------------------------------------------------------------------------
// CpuidTx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI CpuidTx(
DWORD index, // CPUID index
PDWORD eax,
PDWORD ebx,
PDWORD ecx,
PDWORD edx,
DWORD_PTR threadAffinityMask
);
//-----------------------------------------------------------------------------
// CpuidPx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI CpuidPx(
DWORD index, // CPUID index
PDWORD eax,
PDWORD ebx,
PDWORD ecx,
PDWORD edx,
DWORD_PTR processAffinityMask
);
//-----------------------------------------------------------------------------
// Rdtsc
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI Rdtsc(
PDWORD eax, // bit 0-31
PDWORD edx // bit 32-63
);
//-----------------------------------------------------------------------------
// RdmsrTx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI RdtscTx(
PDWORD eax, // bit 0-31
PDWORD edx, // bit 32-63
DWORD_PTR threadAffinityMask
);
//-----------------------------------------------------------------------------
// RdmsrPx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI RdtscPx(
PDWORD eax, // bit 0-31
PDWORD edx, // bit 32-63
DWORD_PTR processAffinityMask
);
//-----------------------------------------------------------------------------
// Hlt
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI Hlt();
//-----------------------------------------------------------------------------
// HltTx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI HltTx(
DWORD_PTR threadAffinityMask
);
//-----------------------------------------------------------------------------
// HltPx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI HltTx(
DWORD_PTR processAffinityMask
);
/******************************************************************************
**
** I/O
**
******************************************************************************/
//-----------------------------------------------------------------------------
// ReadIoPortByte
//-----------------------------------------------------------------------------
BYTE // Read Value
WINAPI ReadIoPortByte(
WORD port // I/O port address
);
//-----------------------------------------------------------------------------
// ReadIoPortWord
//-----------------------------------------------------------------------------
WORD // Read Value
WINAPI ReadIoPortWord(
WORD port // I/O port address
);
//-----------------------------------------------------------------------------
// ReadIoPortDword
//-----------------------------------------------------------------------------
DWORD // Read Value
WINAPI ReadIoPortDword(
WORD port // I/O port address
);
//-----------------------------------------------------------------------------
// ReadIoPortByteEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI ReadIoPortByteEx(
WORD port, // I/O port address
PBYTE value // Read Value
);
//-----------------------------------------------------------------------------
// ReadIoPortWordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI ReadIoPortWordEx(
WORD port, // I/O port address
PWORD value // Read Value
);
//-----------------------------------------------------------------------------
// ReadIoPortDwordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI ReadIoPortDwordEx(
WORD port, // I/O port address
PDWORD value // Read Value
);
//-----------------------------------------------------------------------------
// WriteIoPortByte
//-----------------------------------------------------------------------------
VOID
WINAPI WriteIoPortByte(
WORD port, // I/O port address
BYTE value // Write Value
);
//-----------------------------------------------------------------------------
// WriteIoPortDword
//-----------------------------------------------------------------------------
VOID
WINAPI WriteIoPortDword(
WORD port, // I/O port address
DWORD value // Write Value
);
//-----------------------------------------------------------------------------
// WriteIoPortWord
//-----------------------------------------------------------------------------
VOID
WINAPI WriteIoPortWord(
WORD port, // I/O port address
WORD value // Write Value
);
//-----------------------------------------------------------------------------
// WriteIoPortByteEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WriteIoPortByteEx(
WORD port, // I/O port address
BYTE value // Write Value
);
//-----------------------------------------------------------------------------
// WriteIoPortWordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WriteIoPortWordEx(
WORD port, // I/O port address
WORD value // Write Value
);
//-----------------------------------------------------------------------------
// WriteIoPortDwordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WriteIoPortDwordEx(
WORD port, // I/O port address
DWORD value // Write Value
);
/******************************************************************************
**
** PCI
**
******************************************************************************/
// pciAddress
// 0- 2: Function Number
// 3- 7: Device Number
// 8-15: PCI Bus Number
// 16-31: Reserved
// 0xFFFFFFFF : Error
//-----------------------------------------------------------------------------
// SetPciMaxBusNo
//-----------------------------------------------------------------------------
VOID
WINAPI SetPciMaxBusIndex(
BYTE max // Max PCI Bus to Scan
);
//-----------------------------------------------------------------------------
// ReadPciConfigByte
//-----------------------------------------------------------------------------
BYTE // Read Value
WINAPI ReadPciConfigByte(
DWORD pciAddress, // PCI Device Address
BYTE regAddress // Configuration Address 0-255
);
//-----------------------------------------------------------------------------
// ReadPciConfigWord
//-----------------------------------------------------------------------------
WORD // Read Value
WINAPI ReadPciConfigWord(
DWORD pciAddress, // PCI Device Address
BYTE regAddress // Configuration Address 0-255
);
//-----------------------------------------------------------------------------
// ReadPciConfigDword
//-----------------------------------------------------------------------------
DWORD // Read Value
WINAPI ReadPciConfigDword(
DWORD pciAddress, // PCI Device Address
BYTE regAddress // Configuration Address 0-255
);
//-----------------------------------------------------------------------------
// ReadPciConfigByteEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI ReadPciConfigByteEx(
DWORD pciAddress, // PCI Device Address
DWORD regAddress, // Configuration Address 0-whatever
PBYTE value // Read Value
);
//-----------------------------------------------------------------------------
// ReadPciConfigWordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI ReadPciConfigWordEx(
DWORD pciAddress, // PCI Device Address
DWORD regAddress, // Configuration Address 0-whatever
PWORD value // Read Value
);
//-----------------------------------------------------------------------------
// ReadPciConfigDwordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI ReadPciConfigDwordEx(
DWORD pciAddress, // PCI Device Address
DWORD regAddress, // Configuration Address 0-whatever
PDWORD value // Read Value
);
//-----------------------------------------------------------------------------
// WritePciConfigByte
//-----------------------------------------------------------------------------
VOID
WINAPI WritePciConfigByte(
DWORD pciAddress, // PCI Device Address
BYTE regAddress, // Configuration Address 0-255
BYTE value // Write Value
);
//-----------------------------------------------------------------------------
// WritePciConfigWord
//-----------------------------------------------------------------------------
VOID
WINAPI WritePciConfigWord(
DWORD pciAddress, // PCI Device Address
BYTE regAddress, // Configuration Address 0-255
WORD value // Write Value
);
//-----------------------------------------------------------------------------
// WritePciConfigDword
//-----------------------------------------------------------------------------
VOID
WINAPI WritePciConfigDword(
DWORD pciAddress, // PCI Device Address
BYTE regAddress, // Configuration Address 0-255
DWORD value // Write Value
);
//-----------------------------------------------------------------------------
// WritePciConfigByteEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WritePciConfigByteEx(
DWORD pciAddress, // PCI Device Address
DWORD regAddress, // Configuration Address 0-whatever
BYTE value // Write Value
);
//-----------------------------------------------------------------------------
// WritePciConfigWordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WritePciConfigWordEx(
DWORD pciAddress, // PCI Device Address
DWORD regAddress, // Configuration Address 0-whatever
WORD value // Write Value
);
//-----------------------------------------------------------------------------
// WritePciConfigDwordEx
//-----------------------------------------------------------------------------
BOOL // TRUE: success, FALSE: failure
WINAPI WritePciConfigDwordEx(
DWORD pciAddress, // PCI Device Address
DWORD regAddress, // Configuration Address 0-whatever
DWORD value // Write Value
);
//-----------------------------------------------------------------------------
// FindPciDeviceById
//-----------------------------------------------------------------------------
DWORD // pciAddress, 0xFFFFFFFF: failure
WINAPI FindPciDeviceById(
WORD vendorId, // Vendor ID
WORD deviceId, // Device ID
BYTE index // Index
);
//-----------------------------------------------------------------------------
// FindPciDeviceByClass
//-----------------------------------------------------------------------------
DWORD // pciAddress, 0xFFFFFFFF: failure
WINAPI FindPciDeviceByClass(
BYTE baseClass, // Base Class
BYTE subClass, // Sub Class
BYTE programIf, // Program Interface
BYTE index // Index
);
/******************************************************************************
**
** Memory (Special API)
**
******************************************************************************/
#ifdef _PHYSICAL_MEMORY_SUPPORT
//-----------------------------------------------------------------------------
// ReadDmiMemory
//-----------------------------------------------------------------------------
DWORD // Read size(byte), 0: failure
WINAPI ReadDmiMemory(
PBYTE buffer, // Buffer
DWORD count, // Count
DWORD unitSize // Unit Size (BYTE, WORD, DWORD)
);
//-----------------------------------------------------------------------------
// ReadPhysicalMemory
//-----------------------------------------------------------------------------
DWORD // Read size(byte), 0: failure
WINAPI ReadPhysicalMemory(
DWORD_PTR address, // Physical Memory Address
PBYTE buffer, // Buffer
DWORD count, // Count
DWORD unitSize // Unit Size (BYTE, WORD, DWORD)
);
//-----------------------------------------------------------------------------
// WritePhysicalMemory
//-----------------------------------------------------------------------------
DWORD // Write size(byte), 0: failure
WINAPI WritePhysicalMemory(
DWORD_PTR address, // Physical Memory Address
PBYTE buffer, // Buffer
DWORD count, // Count
DWORD unitSize // Unit Size (BYTE, WORD, DWORD)
);
#endif

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| i2c_smbus_i801.cpp |
| |
| i801 SMBUS driver for Windows |
| i801 SMBUS driver for MacOS |
| |
| Adam Honse (CalcProgrammer1) 29 Jan 2019 |
| Portions based on Linux source code |
@@ -10,47 +10,22 @@
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "macUSPCIOAccess.h"
#include "Detector.h"
#include "i2c_smbus_i801.h"
#include "ResourceManager.h"
#ifdef _WIN32
#include "OlsApi.h"
#include "wmi.h"
#elif _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
#endif
#include "LogManager.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
using namespace std::chrono_literals;
i2c_smbus_i801::i2c_smbus_i801()
{
#ifdef _WIN32
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
bool shared_smbus_access = true;
if(drivers_settings.contains("shared_smbus_access"))
{
shared_smbus_access = drivers_settings["shared_smbus_access"].get<bool>();
}
if(shared_smbus_access)
{
global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
}
#endif
}
i2c_smbus_i801::~i2c_smbus_i801()
{
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
CloseHandle(global_smbus_access_handle);
}
#endif
}
/* Return negative errno on error. */
@@ -519,22 +494,8 @@ int i2c_smbus_i801::i801_wait_intr()
s32 i2c_smbus_i801::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
WaitForSingleObject(global_smbus_access_handle, INFINITE);
}
#endif
s32 result = i801_access(addr, read_write, command, size, data);
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
ReleaseMutex(global_smbus_access_handle);
}
#endif
return result;
}
@@ -543,103 +504,6 @@ s32 i2c_smbus_i801::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u8
return -1;
}
#ifdef _WIN32
bool i2c_smbus_i801_detect()
{
if(!InitializeOls() || GetDllStatus())
{
LOG_INFO("WinRing0 is not loaded, i801 I2C bus detection aborted");
return(false);
}
i2c_smbus_interface * bus;
HRESULT hres;
Wmi wmi;
// Query WMI for Win32_PnPSignedDriver entries with names matching "SMBUS" or "SM BUS"
// These devices may be browsed under Device Manager -> System Devices
std::vector<QueryObj> q_res_PnPSignedDriver;
hres = wmi.query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'", q_res_PnPSignedDriver);
if (hres)
{
LOG_INFO("WMI query failed, i801 I2C bus detection aborted");
return(false);
}
// For each detected SMBus adapter, try enumerating it as either AMD or Intel
for (QueryObj &i : q_res_PnPSignedDriver)
{
// Intel SMBus controllers do show I/O resources in Device Manager
// Analysis of many Intel boards has shown that Intel SMBus adapter I/O space varies between boards
// We can query Win32_PnPAllocatedResource entries and look up the PCI device ID to find the allocated I/O space
// Intel SMBus adapters use the i801 driver
if ((i["Manufacturer"].find("Intel") != std::string::npos)
|| (i["Manufacturer"].find("INTEL") != std::string::npos))
{
std::string rgx1 = ".+" + q_res_PnPSignedDriver[0]["DeviceID"].substr(4, 33) + ".+";
AdditionalFilters filters;
filters.emplace("Dependent", rgx1);
filters.emplace("Antecedent", ".*Port.*");
std::vector<QueryObj> q_res_PNPAllocatedResource;
hres = wmi.query("SELECT * FROM Win32_PnPAllocatedResource", q_res_PNPAllocatedResource, &filters);
std::regex rgx2(".*StartingAddress=\"(\\d+)\".*");
std::smatch matches;
// Query the StartingAddress for the matching device ID and use it to enumerate the bus
if (!q_res_PNPAllocatedResource.empty() && std::regex_search(q_res_PNPAllocatedResource[0]["Antecedent"], matches, rgx2))
{
unsigned int IORangeStart = std::stoi(matches[1].str());
std::string pnp_str = i["DeviceID"];
std::size_t ven_loc = pnp_str.find("VEN_");
std::size_t dev_loc = pnp_str.find("DEV_");
std::size_t sub_loc = pnp_str.find("SUBSYS_");
std::string ven_str = pnp_str.substr(ven_loc + 4, 4);
std::string dev_str = pnp_str.substr(dev_loc + 4, 4);
std::string sbv_str = pnp_str.substr(sub_loc + 11, 4);
std::string sbd_str = pnp_str.substr(sub_loc + 7, 4);
int ven_id = (int)std::stoul(ven_str, nullptr, 16);
int dev_id = (int)std::stoul(dev_str, nullptr, 16);
int sbv_id = (int)std::stoul(sbv_str, nullptr, 16);
int sbd_id = (int)std::stoul(sbd_str, nullptr, 16);
DWORD pciAddress = FindPciDeviceById(ven_id, dev_id, 0);
if(pciAddress == 0xFFFFFFFF)
{
continue;
}
uint8_t host_config = (uint8_t)ReadPciConfigWord(pciAddress, SMBHSTCFG);
if ((host_config & SMBHSTCFG_HST_EN) == 0)
{
continue;
}
bus = new i2c_smbus_i801();
bus->pci_vendor = ven_id;
bus->pci_device = dev_id;
bus->pci_subsystem_vendor = sbv_id;
bus->pci_subsystem_device = sbd_id;
strcpy(bus->device_name, i["Description"].c_str());
((i2c_smbus_i801 *)bus)->i801_smba = IORangeStart;
ResourceManager::get()->RegisterI2CBus(bus);
}
}
}
return(true);
}
#elif _MACOSX_X86_X64
bool i2c_smbus_i801_detect()
{
if(!GetMacUSPCIODriverStatus())
@@ -675,6 +539,4 @@ bool i2c_smbus_i801_detect()
return(true);
}
#endif
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_i801_detect);

View File

@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| i2c_smbus_i801.h |
| |
| i801 SMBUS driver for Windows |
| i801 SMBUS driver for MacOS |
| |
| Adam Honse (CalcProgrammer1) 29 Jan 2019 |
| Portions based on Linux source code |
@@ -14,10 +14,6 @@
#include "i2c_smbus.h"
#ifdef _WIN32
#include <Windows.h>
#endif
/* BIT shifting macro */
#define BIT(x) ( 1 << x )
@@ -87,10 +83,6 @@
#define SMBHSTCFG 0x040
#define SMBHSTCFG_HST_EN BIT(0)
#ifdef _WIN32
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
#endif
class i2c_smbus_i801 : public i2c_smbus_interface
{
public:
@@ -109,8 +101,4 @@ private:
int i801_wait_intr();
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
#ifdef _WIN32
HANDLE global_smbus_access_handle = NULL;
#endif
};

View File

@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| i2c_smbus_nct6775.cpp |
| |
| Nuvoton NCT67xx SMBUS driver for Windows |
| Nuvoton NCT67xx SMBUS driver for MacOS |
| |
| Adam Honse (CalcProgrammer1) 19 May 2019 |
| |
@@ -9,14 +9,11 @@
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "macUSPCIOAccess.h"
#include "Detector.h"
#include "i2c_smbus_nct6775.h"
#include "LogManager.h"
#ifdef _WIN32
#include "OlsApi.h"
#elif _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
#endif
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "super_io.h"
@@ -25,29 +22,10 @@ using namespace std::chrono_literals;
i2c_smbus_nct6775::i2c_smbus_nct6775()
{
#ifdef _WIN32
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
bool shared_smbus_access = true;
if(drivers_settings.contains("shared_smbus_access"))
{
shared_smbus_access = drivers_settings["shared_smbus_access"].get<bool>();
}
if(shared_smbus_access)
{
global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
}
#endif
}
i2c_smbus_nct6775::~i2c_smbus_nct6775()
{
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
CloseHandle(global_smbus_access_handle);
}
#endif
}
s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
@@ -223,22 +201,8 @@ s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int
s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
WaitForSingleObject(global_smbus_access_handle, INFINITE);
}
#endif
s32 result = nct6775_access(addr, read_write, command, size, data);
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
ReleaseMutex(global_smbus_access_handle);
}
#endif
return result;
}
@@ -249,19 +213,11 @@ s32 i2c_smbus_nct6775::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/,
bool i2c_smbus_nct6775_detect()
{
#ifdef _WIN32
if(!InitializeOls() || GetDllStatus())
{
LOG_INFO("WinRing0 is not loaded, nct6775 I2C bus detection aborted");
return(false);
}
#elif _MACOSX_X86_X64
if(!GetMacUSPCIODriverStatus())
{
LOG_INFO("macUSPCIO is not loaded, nct6775 I2C bus detection aborted");
return(false);
}
#endif
i2c_smbus_interface* bus;
int sioaddr = 0x2E;

View File

@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| i2c_smbus_nct6775.h |
| |
| Nuvoton NCT67xx SMBUS driver for Windows |
| Nuvoton NCT67xx SMBUS driver for MacOS |
| |
| Adam Honse (CalcProgrammer1) 19 May 2019 |
| |
@@ -12,9 +12,6 @@
#pragma once
#include "i2c_smbus.h"
#ifdef _WIN32
#include <Windows.h>
#endif
#define SMBHSTDAT (0 + nct6775_smba)
#define SMBBLKSZ (1 + nct6775_smba)
@@ -50,10 +47,6 @@
/* Other settings */
#define NCT6775_MAX_RETRIES 400
#ifdef _WIN32
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
#endif
class i2c_smbus_nct6775: public i2c_smbus_interface
{
public:
@@ -65,8 +58,4 @@ private:
s32 nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
#ifdef _WIN32
HANDLE global_smbus_access_handle = NULL;
#endif
};

View File

@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| i2c_smbus_piix4.cpp |
| |
| PIIX4 SMBUS driver for Windows |
| PIIX4 SMBUS driver for MacOS |
| |
| Adam Honse (CalcProgrammer1) 08 Aug 2018 |
| Portions based on Linux source code |
@@ -10,17 +10,13 @@
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include <unistd.h>
#include "macUSPCIOAccess.h"
#include "Detector.h"
#include "i2c_smbus_piix4.h"
#include "LogManager.h"
#ifdef _WIN32
#include "OlsApi.h"
#include "wmi.h"
#elif _MACOSX_X86_X64
#include <unistd.h>
#include "macUSPCIOAccess.h"
#include "pci_ids.h"
#endif
#include "ResourceManager.h"
#include "SettingsManager.h"
@@ -33,43 +29,12 @@ i2c_smbus_piix4::i2c_smbus_piix4()
{
amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get<bool>();
}
#ifdef _WIN32
if(amd_smbus_reduce_cpu)
{
delay_timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
if(delay_timer == NULL) // high resolution timer not supported
{
delay_timer = CreateWaitableTimer(NULL, TRUE, NULL); // create regular timer instead
}
}
bool shared_smbus_access = true;
if(drivers_settings.contains("shared_smbus_access"))
{
shared_smbus_access = drivers_settings["shared_smbus_access"].get<bool>();
}
if(shared_smbus_access)
{
global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
}
#else
delay_timer = amd_smbus_reduce_cpu;
#endif
}
i2c_smbus_piix4::~i2c_smbus_piix4()
{
#ifdef _WIN32
if(delay_timer != NULL)
{
CloseHandle(delay_timer);
}
if(global_smbus_access_handle != NULL)
{
CloseHandle(global_smbus_access_handle);
}
#endif
}
//Logic adapted from piix4_transaction() in i2c-piix4.c
@@ -105,21 +70,8 @@ int i2c_smbus_piix4::piix4_transaction()
| if this bit is set. Note that there may be moderate latency before the transaction begins and the Host Busy bit |
| gets set. |
\*---------------------------------------------------------------------------------------------------------------*/
#ifdef _WIN32
if(delay_timer != NULL)
{
LARGE_INTEGER retry_delay;
retry_delay.QuadPart = RETRY_DELAY_US * -10;
temp = 0;
do
{
SetWaitableTimer(delay_timer, &retry_delay, 0, NULL, NULL, FALSE);
WaitForSingleObject(delay_timer, INFINITE);
temp = ReadIoPortByte(SMBHSTSTS);
}
while((++timeout < MAX_TIMEOUT) && ((temp & 0x03) != 0x02));
}
#else
if(delay_timer)
{
do
@@ -129,7 +81,6 @@ int i2c_smbus_piix4::piix4_transaction()
}
while((++timeout < MAX_TIMEOUT) && ((temp & 0x03) != 0x02));
}
#endif
else
{
std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
@@ -282,22 +233,8 @@ s32 i2c_smbus_piix4::piix4_access(u16 addr, char read_write, u8 command, int siz
s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
WaitForSingleObject(global_smbus_access_handle, INFINITE);
}
#endif
s32 result = piix4_access(addr, read_write, command, size, data);
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
ReleaseMutex(global_smbus_access_handle);
}
#endif
return result;
}
@@ -305,79 +242,7 @@ s32 i2c_smbus_piix4::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u
{
return -1;
}
#ifdef _WIN32
bool i2c_smbus_piix4_detect()
{
if(!InitializeOls() || GetDllStatus())
{
LOG_INFO("WinRing0 is not loaded, piix4 I2C bus detection aborted");
return(false);
}
i2c_smbus_interface * bus;
HRESULT hres;
Wmi wmi;
// Query WMI for Win32_PnPSignedDriver entries with names matching "SMBUS" or "SM BUS"
// These devices may be browsed under Device Manager -> System Devices
std::vector<QueryObj> q_res_PnPSignedDriver;
hres = wmi.query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'", q_res_PnPSignedDriver);
if (hres)
{
LOG_INFO("WMI query failed, piix4 I2C bus detection aborted");
return(false);
}
// For each detected SMBus adapter, try enumerating it as either AMD or Intel
for (QueryObj &i : q_res_PnPSignedDriver)
{
// AMD SMBus controllers do not show any I/O resources allocated in Device Manager
// Analysis of many AMD boards has shown that AMD SMBus controllers have two adapters with fixed I/O spaces at 0x0B00 and 0x0B20
// AMD SMBus adapters use the PIIX4 driver
if (i["Manufacturer"].find("Advanced Micro Devices, Inc") != std::string::npos)
{
std::string pnp_str = i["DeviceID"];
std::size_t ven_loc = pnp_str.find("VEN_");
std::size_t dev_loc = pnp_str.find("DEV_");
std::size_t sub_loc = pnp_str.find("SUBSYS_");
std::string ven_str = pnp_str.substr(ven_loc + 4, 4);
std::string dev_str = pnp_str.substr(dev_loc + 4, 4);
std::string sbv_str = pnp_str.substr(sub_loc + 11, 4);
std::string sbd_str = pnp_str.substr(sub_loc + 7, 4);
int ven_id = (int)std::stoul(ven_str, nullptr, 16);
int dev_id = (int)std::stoul(dev_str, nullptr, 16);
int sbv_id = (int)std::stoul(sbv_str, nullptr, 16);
int sbd_id = (int)std::stoul(sbd_str, nullptr, 16);
bus = new i2c_smbus_piix4();
bus->pci_vendor = ven_id;
bus->pci_device = dev_id;
bus->pci_subsystem_vendor = sbv_id;
bus->pci_subsystem_device = sbd_id;
strcpy(bus->device_name, i["Description"].c_str());
strcat(bus->device_name, " at 0x0B00");
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B00;
ResourceManager::get()->RegisterI2CBus(bus);
bus = new i2c_smbus_piix4();
bus->pci_vendor = ven_id;
bus->pci_device = dev_id;
bus->pci_subsystem_vendor = sbv_id;
bus->pci_subsystem_device = sbd_id;
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B20;
strcpy(bus->device_name, i["Description"].c_str());
strcat(bus->device_name, " at 0x0B20");
ResourceManager::get()->RegisterI2CBus(bus);
}
}
return(true);
}
#elif _MACOSX_X86_X64
bool i2c_smbus_piix4_detect()
{
if(!GetMacUSPCIODriverStatus())
@@ -419,6 +284,5 @@ bool i2c_smbus_piix4_detect()
return(true);
}
#endif
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_piix4_detect);

View File

@@ -1,7 +1,7 @@
/*---------------------------------------------------------*\
| i2c_smbus_piix4.h |
| |
| PIIX4 SMBUS driver for Windows |
| PIIX4 SMBUS driver for MacOS |
| |
| Adam Honse (CalcProgrammer1) 08 Aug 2018 |
| Portions based on Linux source code |
@@ -13,9 +13,6 @@
#pragma once
#include "i2c_smbus.h"
#ifdef _WIN32
#include "windows.h"
#endif
// PIIX4 SMBus address offsets
#define SMBHSTSTS (0 + piix4_smba)
@@ -41,10 +38,6 @@
#define PIIX4_WORD_DATA 0x0C
#define PIIX4_BLOCK_DATA 0x14
#ifdef _WIN32
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
#endif
class i2c_smbus_piix4 : public i2c_smbus_interface
{
public:
@@ -57,10 +50,6 @@ private:
s32 piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
#ifdef _WIN32
HANDLE delay_timer = NULL;
HANDLE global_smbus_access_handle = NULL;
#else
bool delay_timer;
#endif
};

View File

@@ -0,0 +1,558 @@
/*---------------------------------------------------------*\
| i2c_smbus_pawnio.cpp |
| |
| PawnIO SMBUS driver for Windows |
| |
| Stephen Horvath (Steve-Tech) 04 May 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include <string>
#include "Detector.h"
#include "i2c_smbus_pawnio.h"
#include "LogManager.h"
#include "PawnIOLib.h"
#include "ResourceManager.h"
#include "SettingsManager.h"
#include "wmi.h"
std::unordered_map<std::string, int> i2c_smbus_pawnio::using_handle;
i2c_smbus_pawnio::i2c_smbus_pawnio(HANDLE handle, std::string name)
{
/*-----------------------------------------------------*\
| Get driver settings |
\*-----------------------------------------------------*/
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
/*-----------------------------------------------------*\
| Get shared SMBus access setting |
\*-----------------------------------------------------*/
bool shared_smbus_access = true;
if(drivers_settings.contains("shared_smbus_access"))
{
shared_smbus_access = drivers_settings["shared_smbus_access"].get<bool>();
}
/*-----------------------------------------------------*\
| Create global SMBus mutex if enabled |
\*-----------------------------------------------------*/
if(shared_smbus_access)
{
global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
}
/*-----------------------------------------------------*\
| Store bus information |
| TODO: Remove name field once all drivers use the same |
| ioctl names |
\*-----------------------------------------------------*/
this->handle = handle;
this->name = name;
using_handle[name]++;
}
i2c_smbus_pawnio::~i2c_smbus_pawnio()
{
/*-----------------------------------------------------*\
| Close global SMBus mutex |
\*-----------------------------------------------------*/
if(global_smbus_access_handle != NULL)
{
CloseHandle(global_smbus_access_handle);
}
/*-----------------------------------------------------*\
| TODO: find a way to do this without name field |
\*-----------------------------------------------------*/
if(--using_handle[name] == 0 && pawnio_close(handle))
{
LOG_ERROR("PawnIO failed to close");
}
}
s32 i2c_smbus_pawnio::pawnio_read(u8 addr, char /*read_write*/, u8 command, int size, i2c_smbus_data* data)
{
SIZE_T return_size;
switch(size)
{
case I2C_SMBUS_BYTE:
{
const SIZE_T in_size = 1;
ULONG64 in[in_size] = {addr};
const SIZE_T out_size = 1;
ULONG64 out[out_size];
/*---------------------------------------------*\
| Execute PawnIO read_byte ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_read_byte").c_str(), in, in_size, out, out_size, &return_size);
data->byte = (u8)out[0];
return(status ? -EIO : 0);
}
case I2C_SMBUS_BYTE_DATA:
{
const SIZE_T in_size = 2;
ULONG64 in[in_size] = {addr, command};
const SIZE_T out_size = 1;
ULONG64 out[out_size];
/*---------------------------------------------*\
| Execute PawnIO read_byte_data ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_read_byte_data").c_str(), in, in_size, out, out_size, &return_size);
data->byte = (u8)out[0];
return(status ? -EIO : 0);
}
case I2C_SMBUS_WORD_DATA:
{
const SIZE_T in_size = 2;
ULONG64 in[in_size] = {addr, command};
const SIZE_T out_size = 1;
ULONG64 out[out_size];
/*---------------------------------------------*\
| Execute PawnIO read_word_data ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_read_word_data").c_str(), in, in_size, out, out_size, &return_size);
data->word = (u16)out[0];
return(status ? -EIO : 0);
}
case I2C_SMBUS_BLOCK_DATA:
{
const SIZE_T in_size = 2;
ULONG64 in[in_size] = {addr, command};
/*---------------------------------------------*\
| Calculate output data buffer size |
| Pawn only deals with 64-bit cells, divide by |
| 8 to convert bytes to qwords. |
| The first cell is also the length. |
\*---------------------------------------------*/
const SIZE_T out_size = 1 + (I2C_SMBUS_BLOCK_MAX / 8);
ULONG64 out[out_size];
/*---------------------------------------------*\
| Execute PawnIO read_block_data ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_read_block_data").c_str(), in, in_size, out, out_size, &return_size);
if(status)
{
return(-EIO);
}
if(out[0] == 0 || out[0] > I2C_SMBUS_BLOCK_MAX)
{
return(-EPROTO);
}
/*---------------------------------------------*\
| Unpack bytes from 64bit Pawn cells |
\*---------------------------------------------*/
u8 *out_bytes = (u8*)(&out[1]);
memcpy(&data->block[1], out_bytes, out[0]);
return(0);
}
default:
return(-EOPNOTSUPP);
}
}
s32 i2c_smbus_pawnio::pawnio_write(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{
SIZE_T return_size;
switch(size)
{
case I2C_SMBUS_QUICK:
{
const SIZE_T in_size = 2;
ULONG64 in[in_size] = {addr, (u8)read_write};
/*---------------------------------------------*\
| Execute PawnIO write_quick ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_write_quick").c_str(), in, in_size, NULL, 0, &return_size);
return(status ? -EIO : 0);
}
case I2C_SMBUS_BYTE:
{
const SIZE_T in_size = 2;
ULONG64 in[in_size] = {addr, data->byte};
/*---------------------------------------------*\
| Execute PawnIO write_byte ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_write_byte").c_str(), in, in_size, NULL, 0, &return_size);
return(status ? -EIO : 0);
}
case I2C_SMBUS_BYTE_DATA:
{
const SIZE_T in_size = 3;
ULONG64 in[in_size] = {addr, command, data->byte};
/*---------------------------------------------*\
| Execute PawnIO write_byte_data ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_write_byte_data").c_str(), in, in_size, NULL, 0, &return_size);
return(status ? -EIO : 0);
}
case I2C_SMBUS_WORD_DATA:
{
const SIZE_T in_size = 3;
ULONG64 in[in_size] = {addr, command, data->word};
/*---------------------------------------------*\
| Execute PawnIO write_word_data ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_write_word_data").c_str(), in, in_size, NULL, 0, &return_size);
return(status ? -EIO : 0);
}
case I2C_SMBUS_BLOCK_DATA:
{
SIZE_T len = data->block[0];
if(len == 0 || len > I2C_SMBUS_BLOCK_MAX)
{
return -EINVAL;
}
const SIZE_T in_size = 3 + (I2C_SMBUS_BLOCK_MAX/8);
ULONG64 in[3 + (I2C_SMBUS_BLOCK_MAX/8)] = {addr, command, len};
/*---------------------------------------------*\
| Pack bytes into 64bit Pawn cells |
\*---------------------------------------------*/
u8 *in_bytes = (u8*)&in[3];
memcpy(in_bytes, &data->block[1], len);
/*---------------------------------------------*\
| Execute PawnIO write_block_data ioctl |
\*---------------------------------------------*/
HRESULT status = pawnio_execute(handle, ("ioctl_" + name + "_write_block_data").c_str(), in, in_size, NULL, 0, &return_size);
return(status ? -EIO : 0);
}
default:
return(-EOPNOTSUPP);
}
}
s32 i2c_smbus_pawnio::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{
if(global_smbus_access_handle != NULL)
{
WaitForSingleObject(global_smbus_access_handle, INFINITE);
}
int status = -ENXIO;
if(read_write && size != I2C_SMBUS_QUICK) {
status = pawnio_read(addr, read_write, command, size, data);
}
else
{
status = pawnio_write(addr, read_write, command, size, data);
}
if(global_smbus_access_handle != NULL)
{
ReleaseMutex(global_smbus_access_handle);
}
return(status);
}
s32 i2c_smbus_pawnio::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u8* /*data*/)
{
return(-1);
}
// TODO: Find a better place for this function
HRESULT i2c_smbus_pawnio::start_pawnio(std::string filename, PHANDLE phandle)
{
char exePath[MAX_PATH];
HANDLE handle;
HRESULT status;
/*-----------------------------------------------------*\
| Open PawnIO driver |
\*-----------------------------------------------------*/
status = pawnio_open(phandle);
/*-----------------------------------------------------*\
| Check result |
\*-----------------------------------------------------*/
if(status)
{
if(status == E_ACCESSDENIED)
{
LOG_ERROR("Permission Denied, PawnIO initialization aborted");
}
else
{
LOG_ERROR("Could not open PawnIO, PawnIO initialization aborted");
}
return(status);
}
handle = *phandle;
/*-----------------------------------------------------*\
| Get the path of the executable |
\*-----------------------------------------------------*/
if(!GetModuleFileNameA(NULL, exePath, MAX_PATH))
{
LOG_ERROR("Failed to get executable path, PawnIO initialization aborted");
return E_FAIL;
}
/*-----------------------------------------------------*\
| Construct the path to `filename` in the executable's |
| directory |
\*-----------------------------------------------------*/
std::filesystem::path exeDir = std::filesystem::path(exePath).parent_path();
std::filesystem::path filePath = exeDir / filename;
/*-----------------------------------------------------*\
| Check if the file exists |
\*-----------------------------------------------------*/
if(!std::filesystem::exists(filePath))
{
LOG_ERROR("Failed to find %s in the executable's directory, PawnIO initialization aborted", filename.c_str());
return(E_FAIL);
}
/*-----------------------------------------------------*\
| Open the file |
\*-----------------------------------------------------*/
std::ifstream file(filePath, std::ios::binary);
if(!file.is_open())
{
LOG_ERROR("Failed to open %s, PawnIO initialization aborted", filename.c_str());
return(E_FAIL);
}
/*-----------------------------------------------------*\
| Read the contents of the file into a vector of bytes |
\*-----------------------------------------------------*/
std::vector<char> blob((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
/*-----------------------------------------------------*\
| Close the file |
\*-----------------------------------------------------*/
file.close();
/*-----------------------------------------------------*\
| Load the file into PawnIO |
\*-----------------------------------------------------*/
status = pawnio_load(handle, reinterpret_cast<const UCHAR*>(blob.data()), blob.size());
/*-----------------------------------------------------*\
| Check if the load was successful |
\*-----------------------------------------------------*/
if(status)
{
LOG_ERROR("Failed to load %s, PawnIO initialization aborted", filename.c_str());
return(status);
}
/*-----------------------------------------------------*\
| Log a message and return OK if PawnIO successfully |
| opened |
\*-----------------------------------------------------*/
LOG_INFO("PawnIO initialized");
return(S_OK);
}
s32 piix4_port_sel(HANDLE pawnio_handle, s32 port)
{
const SIZE_T in_size = 1;
ULONG64 in[in_size] = {(ULONG64)port};
const SIZE_T out_size = 1;
ULONG64 out[out_size];
SIZE_T return_size;
HRESULT status;
/*-----------------------------------------------------*\
| Execute PIIX4 port_sel ioctl |
\*-----------------------------------------------------*/
status = pawnio_execute(pawnio_handle, "ioctl_piix4_port_sel", in, in_size, out, 1, &return_size);
return(status ? -EIO : 0);
}
bool i2c_smbus_pawnio_detect()
{
ULONG dll_version;
if(pawnio_version(&dll_version))
{
LOG_INFO("PawnIO is not loaded, PawnIO I2C bus detection aborted");
return(false);
}
i2c_smbus_interface * bus;
HRESULT hres;
Wmi wmi;
HANDLE pawnio_handle;
/*-----------------------------------------------------*\
| Query WMI for Win32_PnPSignedDriver entries with |
| names matching "SMBUS" or "SM BUS". These devices |
| may be browsed under Device Manager -> System Devices |
\*-----------------------------------------------------*/
std::vector<QueryObj> q_res_PnPSignedDriver;
hres = wmi.query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'", q_res_PnPSignedDriver);
if(hres)
{
LOG_INFO("WMI query failed, I2C bus detection aborted");
return(false);
}
/*-----------------------------------------------------*\
| For each detected SMBus adapter, try enumerating it |
| as either AMD (piix4) or Intel (i801) |
\*-----------------------------------------------------*/
for(QueryObj &i : q_res_PnPSignedDriver)
{
/*-------------------------------------------------*\
| Intel SMBus controllers do show I/O resources in |
| Device Manager. Analysis of many Intel boards |
| has shown that Intel SMBus adapter I/O space |
| varies between boards. We can query |
| Win32_PnPAllocatedResource entries and look up |
| the PCI device ID to find the allocated I/O space.|
| |
| Intel SMBus adapters use the i801 driver |
\*-------------------------------------------------*/
if((i["Manufacturer"].find("Intel") != std::string::npos)
|| (i["Manufacturer"].find("INTEL") != std::string::npos))
{
std::string pnp_str = i["DeviceID"];
std::size_t ven_loc = pnp_str.find("VEN_");
std::size_t dev_loc = pnp_str.find("DEV_");
std::size_t sub_loc = pnp_str.find("SUBSYS_");
std::string ven_str = pnp_str.substr(ven_loc + 4, 4);
std::string dev_str = pnp_str.substr(dev_loc + 4, 4);
std::string sbv_str = pnp_str.substr(sub_loc + 11, 4);
std::string sbd_str = pnp_str.substr(sub_loc + 7, 4);
int ven_id = (int)std::stoul(ven_str, nullptr, 16);
int dev_id = (int)std::stoul(dev_str, nullptr, 16);
int sbv_id = (int)std::stoul(sbv_str, nullptr, 16);
int sbd_id = (int)std::stoul(sbd_str, nullptr, 16);
/*---------------------------------------------*\
| Create bus |
\*---------------------------------------------*/
if(i2c_smbus_pawnio::start_pawnio("SmbusI801.bin", &pawnio_handle) != S_OK)
{
return(false);
}
bus = new i2c_smbus_pawnio(pawnio_handle, "i801");
bus->pci_vendor = ven_id;
bus->pci_device = dev_id;
bus->pci_subsystem_vendor = sbv_id;
bus->pci_subsystem_device = sbd_id;
strncpy(bus->device_name, i["Description"].c_str(), sizeof bus->device_name);
ResourceManager::get()->RegisterI2CBus(bus);
}
/*-------------------------------------------------*\
| AMD SMBus adapters use the PIIX4 driver |
\*-------------------------------------------------*/
else if(i["Manufacturer"].find("Advanced Micro Devices, Inc") != std::string::npos)
{
std::string pnp_str = i["DeviceID"];
std::size_t ven_loc = pnp_str.find("VEN_");
std::size_t dev_loc = pnp_str.find("DEV_");
std::size_t sub_loc = pnp_str.find("SUBSYS_");
std::string ven_str = pnp_str.substr(ven_loc + 4, 4);
std::string dev_str = pnp_str.substr(dev_loc + 4, 4);
std::string sbv_str = pnp_str.substr(sub_loc + 11, 4);
std::string sbd_str = pnp_str.substr(sub_loc + 7, 4);
int ven_id = (int)std::stoul(ven_str, nullptr, 16);
int dev_id = (int)std::stoul(dev_str, nullptr, 16);
int sbv_id = (int)std::stoul(sbv_str, nullptr, 16);
int sbd_id = (int)std::stoul(sbd_str, nullptr, 16);
/*---------------------------------------------*\
| Create primary bus |
\*---------------------------------------------*/
if(i2c_smbus_pawnio::start_pawnio("SmbusPIIX4.bin", &pawnio_handle) != S_OK)
{
return(false);
}
/*---------------------------------------------*\
| Select port 0 |
\*---------------------------------------------*/
piix4_port_sel(pawnio_handle, 0);
bus = new i2c_smbus_pawnio(pawnio_handle, "piix4");
bus->pci_vendor = ven_id;
bus->pci_device = dev_id;
bus->pci_subsystem_vendor = sbv_id;
bus->pci_subsystem_device = sbd_id;
strncpy(bus->device_name, i["Description"].c_str(), sizeof bus->device_name);
strncat(bus->device_name, " port 0", sizeof bus->device_name);
ResourceManager::get()->RegisterI2CBus(bus);
/*---------------------------------------------*\
| Create secondary bus |
\*---------------------------------------------*/
if(i2c_smbus_pawnio::start_pawnio("SmbusPIIX4.bin", &pawnio_handle) != S_OK)
{
return(false);
}
/*---------------------------------------------*\
| Select port 1 |
\*---------------------------------------------*/
piix4_port_sel(pawnio_handle, 1);
bus = new i2c_smbus_pawnio(pawnio_handle, "piix4");
bus->pci_vendor = ven_id;
bus->pci_device = dev_id;
bus->pci_subsystem_vendor = sbv_id;
bus->pci_subsystem_device = sbd_id;
strncpy(bus->device_name, i["Description"].c_str(), sizeof bus->device_name);
strncat(bus->device_name, " port 1", sizeof bus->device_name);
ResourceManager::get()->RegisterI2CBus(bus);
}
}
return(true);
}
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_pawnio_detect);

View File

@@ -0,0 +1,42 @@
/*---------------------------------------------------------*\
| i2c_smbus_piix4_pawnio.h |
| |
| PawnIO PIIX4 SMBUS driver for Windows |
| |
| Stephen Horvath (Steve-Tech) 21 Apr 2025 |
| Based on original OpenRGB PIIX4 source code |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <unordered_map>
#include "windows.h"
#include "i2c_smbus.h"
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
class i2c_smbus_pawnio : public i2c_smbus_interface
{
public:
static std::unordered_map<std::string, int> using_handle;
i2c_smbus_pawnio(HANDLE handle, std::string name);
~i2c_smbus_pawnio();
static HRESULT start_pawnio(std::string filename, PHANDLE phandle);
private:
s32 pawnio_read(u8 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
s32 pawnio_write(u8 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
HANDLE global_smbus_access_handle;
std::string name;
HANDLE handle;
};

262
main.cpp Normal file
View File

@@ -0,0 +1,262 @@
/*---------------------------------------------------------*\
| main.cpp |
| |
| Entry point for the OpenRGB application |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "ResourceManager.h"
#include "NetworkServer.h"
#include "LogManager.h"
#include "cli.h"
#include <QApplication>
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#ifdef _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
io_connect_t macUSPCIO_driver_connection;
#endif
#include "OpenRGBDialog.h"
#ifdef __APPLE__
#include "macutils.h"
#endif
#ifdef __linux__
#include <csignal>
#endif
using namespace std::chrono_literals;
/******************************************************************************************\
* *
* InitializeTimerResolutionThreadFunction (Win32) *
* *
* On Windows, the default timer resolution is 15.6ms. For higher accuracy delays, *
* the timer resolution should be set to a shorter interval. The shortest interval *
* that can be set is 0.5ms. *
* *
\******************************************************************************************/
#ifdef _WIN32
void InitializeTimerResolutionThreadFunction()
{
/*-----------------------------------------------------*\
| NtSetTimerResolution function pointer type |
\*-----------------------------------------------------*/
typedef unsigned int NTSTATUS;
typedef NTSTATUS (*NTSETTIMERRESOLUTION)(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);
/*-----------------------------------------------------*\
| PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION = 4, |
| isn't defined in Win10 headers |
\*-----------------------------------------------------*/
PROCESS_POWER_THROTTLING_STATE PowerThrottlingState { PROCESS_POWER_THROTTLING_CURRENT_VERSION, 4, 0 };
ULONG CurrentResolution;
HMODULE NtDllHandle;
NTSETTIMERRESOLUTION NtSetTimerResolution;
/*-----------------------------------------------------*\
| Load ntdll.dll and get pointer to NtSetTimerResolution|
\*-----------------------------------------------------*/
NtDllHandle = LoadLibrary("ntdll.dll");
NtSetTimerResolution = (NTSETTIMERRESOLUTION)GetProcAddress(NtDllHandle, "NtSetTimerResolution");
/*-----------------------------------------------------*\
| Windows 11 requires |
| PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION |
\*-----------------------------------------------------*/
SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottlingState, sizeof(PowerThrottlingState));
/*-----------------------------------------------------*\
| Call NtSetTimerResolution to set timer resolution to |
| 0.5ms every 500ms |
\*-----------------------------------------------------*/
while(1)
{
NtSetTimerResolution(5000, TRUE, &CurrentResolution);
std::this_thread::sleep_for(500ms);
}
}
#endif
void WaitWhileServerOnline(NetworkServer* srv)
{
while (srv->GetOnline())
{
std::this_thread::sleep_for(1s);
};
}
/******************************************************************************************\
* *
* Linux signal handler *
* *
\******************************************************************************************/
#ifdef __linux__
void sigHandler(int s)
{
std::signal(s, SIG_DFL);
qApp->quit();
}
#endif
/******************************************************************************************\
* *
* main *
* *
* Main function. Detects busses and Aura controllers, then opens the main window *
* *
\******************************************************************************************/
int main(int argc, char* argv[])
{
int exitval = EXIT_SUCCESS;
#ifdef _WIN32
/*-----------------------------------------------------*\
| Windows only - Attach console output |
\*-----------------------------------------------------*/
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
/*-------------------------------------------------*\
| We are running under some terminal context; |
| otherwise leave the GUI and CRT alone |
\*-------------------------------------------------*/
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
/*-----------------------------------------------------*\
| Windows only - Start timer resolution correction |
| thread |
\*-----------------------------------------------------*/
std::thread * InitializeTimerResolutionThread;
InitializeTimerResolutionThread = new std::thread(InitializeTimerResolutionThreadFunction);
InitializeTimerResolutionThread->detach();
#endif
/*-----------------------------------------------------*\
| Mac x86/x64 only - Install SMBus Driver macUSPCIO |
\*-----------------------------------------------------*/
#ifdef _MACOSX_X86_X64
InitMacUSPCIODriver();
#endif
/*-----------------------------------------------------*\
| Process command line arguments before detection |
\*-----------------------------------------------------*/
unsigned int ret_flags = cli_pre_detection(argc, argv);
ResourceManager::get()->Initialize(
!(ret_flags & RET_FLAG_NO_AUTO_CONNECT),
!(ret_flags & RET_FLAG_NO_DETECT),
ret_flags & RET_FLAG_START_SERVER,
ret_flags & RET_FLAG_CLI_POST_DETECTION);
/*-----------------------------------------------------*\
| If the command line parser indicates that the GUI |
| should run, or if there were no command line |
| arguments, start the GUI. |
\*-----------------------------------------------------*/
if(ret_flags & RET_FLAG_START_GUI)
{
LOG_TRACE("[main] initializing GUI");
/*-------------------------------------------------*\
| Enable high DPI scaling support |
\*-------------------------------------------------*/
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
#endif
/*-------------------------------------------------*\
| Enable high DPI fractional scaling support on |
| Windows |
\*-------------------------------------------------*/
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) && defined(Q_OS_WIN)
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
QApplication a(argc, argv);
QGuiApplication::setDesktopFileName("org.openrgb.OpenRGB");
LOG_TRACE("[main] QApplication created");
/*-------------------------------------------------*\
| Main UI widget |
\*-------------------------------------------------*/
OpenRGBDialog dlg;
LOG_TRACE("[main] Dialog created");
if(ret_flags & RET_FLAG_I2C_TOOLS)
{
dlg.AddI2CToolsPage();
}
if(ret_flags & RET_FLAG_START_MINIMIZED)
{
#ifdef _WIN32
/*---------------------------------------------*\
| Show the window always, even if it will |
| immediately be hidden. On Windows, events |
| are not delivered to nativeEventFilter (for |
| SuspendResume) until the window has been |
| shown once. |
\*---------------------------------------------*/
dlg.showMinimized();
#endif
#ifdef __APPLE__
MacUtils::ToggleApplicationDocklessState(false);
#endif
dlg.hide();
}
else
{
dlg.show();
}
LOG_TRACE("[main] Ready to exec() the dialog");
#ifdef __linux__
std::signal(SIGINT, sigHandler);
std::signal(SIGTERM, sigHandler);
#endif
exitval = a.exec();
}
else
{
/*-------------------------------------------------*\
| If no GUI is needed, we let the background |
| threads run as long as they need, but we need to |
| AT LEAST wait for initialization to finish |
\*-------------------------------------------------*/
ResourceManager::get()->WaitForInitialization();
if(ret_flags & RET_FLAG_START_SERVER)
{
NetworkServer* server = ResourceManager::get()->GetServer();
if(!server->GetOnline())
{
exitval = EXIT_FAILURE;
}
else
{
WaitWhileServerOnline(server);
}
}
}
ResourceManager::get()->Cleanup();
#ifdef _MACOSX_X86_X64
CloseMacUSPCIODriver();
#endif
LOG_TRACE("OpenRGB finishing with exit code %d", exitval);
return exitval;
}

View File

@@ -519,83 +519,6 @@ static void WaitWhileServerOnline(NetworkServer* srv)
};
}
/*---------------------------------------------------------*\
| InstallWinRing0 |
| |
| Install SMBus Driver WinRing0, If not already installed |
| (Win32) |
\*---------------------------------------------------------*/
void InstallWinRing0()
{
/*-----------------------------------------------------*\
| Driver final location usually |
| C:\windows\system32\drivers\WinRing0x64.sys |
\*-----------------------------------------------------*/
TCHAR winring0_install_location[MAX_PATH];
uint system_path_length = GetSystemDirectory(winring0_install_location, MAX_PATH);
std::string winring0_filename = "WinRing0.sys";
BOOL bIsWow64 = false;
#if _WIN64
winring0_filename = "WinRing0x64.sys";
#else
BOOL (*fnIsWow64Process)(HANDLE, PBOOL) = (BOOL (__cdecl *)(HANDLE, PBOOL))GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if (fnIsWow64Process)
{
fnIsWow64Process(GetCurrentProcess(),&bIsWow64);
}
if(bIsWow64)
{
winring0_filename = "WinRing0x64.sys";
}
#endif
std::strncat(winring0_install_location, "\\drivers\\", MAX_PATH - system_path_length - 1);
std::strncat(winring0_install_location, winring0_filename.c_str(), MAX_PATH - system_path_length - 10);
std::string driver_name = winring0_filename.substr(0, winring0_filename.size() - 4); // driver name: WinRing0 or WinRing0x64
SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager)
{
PVOID wow64_fsredirection_OldValue = NULL;
if(bIsWow64)
{
Wow64DisableWow64FsRedirection(&wow64_fsredirection_OldValue);
}
if(INVALID_FILE_ATTRIBUTES == GetFileAttributes(winring0_install_location) && GetLastError()==ERROR_FILE_NOT_FOUND)
{
char module_path_buffer[MAX_PATH];
GetModuleFileNameA(NULL, module_path_buffer, MAX_PATH);
std::string::size_type exe_loc = std::string(module_path_buffer).find_last_of("\\/");
std::string driver_source_path = std::string(module_path_buffer).substr(0, exe_loc + 1) + winring0_filename;
CopyFile(driver_source_path.c_str(), winring0_install_location, true);
}
if(bIsWow64)
{
Wow64RevertWow64FsRedirection(wow64_fsredirection_OldValue);
}
SC_HANDLE service = OpenService(manager, driver_name.c_str(), SERVICE_ALL_ACCESS);
if(!service)
{
std::string service_sys_path = "System32\\Drivers\\" + winring0_filename;
service = CreateService(manager,
driver_name.c_str(),
driver_name.c_str(),
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
service_sys_path.c_str(),
NULL,
NULL,
NULL,
NULL,
NULL);
}
CloseServiceHandle(service);
CloseServiceHandle(manager);
}
}
/*---------------------------------------------------------*\
| common_main |
| |
@@ -631,11 +554,6 @@ static int common_main(int argc, char* argv[])
InitializeTimerResolutionThread = new std::thread(InitializeTimerResolutionThreadFunction);
InitializeTimerResolutionThread->detach();
/*-----------------------------------------------------*\
| Install SMBus Driver WinRing0 |
\*-----------------------------------------------------*/
InstallWinRing0();
/*-----------------------------------------------------*\
| Initialize ResourceManager |
\*-----------------------------------------------------*/

View File

@@ -10,11 +10,9 @@
\*---------------------------------------------------------*/
#include "super_io.h"
#include "super_io_pawnio.h"
#ifdef _WIN32
#include <Windows.h>
#include "OlsApi.h"
#elif _MACOSX_X86_X64
#if _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
#else
#include <unistd.h>
@@ -34,7 +32,7 @@ int dev_port_fd;
void superio_enter(int ioreg)
{
#if defined(WIN32) || defined(_MACOSX_X86_X64)
#if defined(_MACOSX_X86_X64)
WriteIoPortByte(ioreg, 0x87);
WriteIoPortByte(ioreg, 0x87);
#else
@@ -71,7 +69,7 @@ void superio_enter(int ioreg)
void superio_outb(int ioreg, int reg, int val)
{
#if defined(WIN32) || defined(_MACOSX_X86_X64)
#if defined(_MACOSX_X86_X64)
WriteIoPortByte(ioreg, reg);
WriteIoPortByte(ioreg + 1, val);
#else
@@ -106,7 +104,7 @@ void superio_outb(int ioreg, int reg, int val)
int superio_inb(int ioreg, int reg)
{
#if defined(WIN32) || defined(_MACOSX_X86_X64)
#if defined(_MACOSX_X86_X64)
WriteIoPortByte(ioreg, reg);
return ReadIoPortByte(ioreg + 1);
#else

View File

@@ -9,6 +9,8 @@
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#pragma once
/******************************************************************************************\
* *
* Nuvoton Super IO constants *

View File

@@ -0,0 +1,120 @@
/*---------------------------------------------------------*\
| super_io_pawnio.cpp |
| |
| Functions for interfacing with Super-IO using PawnIO |
| |
| Stephen Horvath (Steve-Tech) 05 May 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "super_io_pawnio.h"
#include <Windows.h>
#include "PawnIOLib.h"
#include "i2c_smbus_pawnio.h"
static HANDLE pawnio_handle = NULL;
static int pawnio_chip_type = 0;
static int addr_to_pawnio(int addr)
{
switch (addr)
{
case 0x2E:
return 0;
case 0x4E:
return 1;
default:
return -1;
}
}
/******************************************************************************************\
* *
* pawnio_superio_enter *
* *
* Put the Super IO chip into Extended Function Mode *
* *
\******************************************************************************************/
void superio_enter(int ioreg)
{
HRESULT status;
SIZE_T return_size;
if (pawnio_handle == NULL)
{
status = i2c_smbus_pawnio::start_pawnio("superio", &pawnio_handle);
if (status != S_OK)
{
// TODO: Figure out how to handle errors
return;
}
}
if (pawnio_chip_type == 0)
{
int in_reg = addr_to_pawnio(ioreg);
if (in_reg == -1) {
return;
}
const SIZE_T in_size = 1;
ULONG64 in[in_size] = {(ULONG64)in_reg};
const SIZE_T out_size = 1;
ULONG64 out[out_size];
status = pawnio_execute(pawnio_handle, "ioctl_detect", in, in_size, out, out_size, &return_size);
if (status != S_OK || out[0] == 0)
{
return;
}
pawnio_chip_type = (int)out[0];
}
pawnio_execute(pawnio_handle, "ioctl_enter", NULL, 0, NULL, 0, &return_size);
}
/******************************************************************************************\
* *
* pawnio_superio_outb *
* *
* Write a byte to the Super IO configuration register *
* *
\******************************************************************************************/
void superio_outb([[maybe_unused]] int ioreg, int reg, int val)
{
const SIZE_T in_size = 2;
ULONG64 in[in_size] = {(ULONG64)reg, (ULONG64)val};
SIZE_T return_size;
pawnio_execute(pawnio_handle, "ioctl_write", in, in_size, NULL, 0, &return_size);
}
/******************************************************************************************\
* *
* pawnio_superio_inb *
* *
* Read a byte from the Super IO configuration register *
* *
\******************************************************************************************/
int superio_inb([[maybe_unused]] int ioreg, int reg)
{
const SIZE_T in_size = 1;
ULONG64 in[in_size] = {(ULONG64)reg};
const SIZE_T out_size = 1;
ULONG64 out[out_size];
SIZE_T return_size;
HRESULT status = pawnio_execute(pawnio_handle, "ioctl_read", in, in_size, out, out_size, &return_size);
if (status != S_OK)
{
return -1;
}
return (int)out[0];
}

View File

@@ -0,0 +1,18 @@
/*---------------------------------------------------------*\
| super_io_pawnio.h |
| |
| Functions for interfacing with Super-IO using PawnIO |
| |
| Stephen Horvath (Steve-Tech) 05 May 2025 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#pragma once
void superio_enter(int ioreg);
void superio_outb(int ioreg, int reg, int val);
int superio_inb(int ioreg, int reg);