Add support for Intel i801 SMBus on MacOS

This commit is contained in:
Shady Nawara 2022-05-31 00:59:07 +00:00 committed by Adam Honse
parent 524675108d
commit e9c382d2e6
6 changed files with 204 additions and 2 deletions

View file

@ -1616,12 +1616,23 @@ macx:contains(QMAKE_HOST.arch, arm64) {
#-------------------------------------------------------------------------------------------# #-------------------------------------------------------------------------------------------#
macx:contains(QMAKE_HOST.arch, x86_64) { macx:contains(QMAKE_HOST.arch, x86_64) {
INCLUDEPATH += \ INCLUDEPATH += \
dependencies/macUSPCIO \
/usr/local/include \ /usr/local/include \
/usr/local/homebrew/include \ /usr/local/homebrew/include \
SOURCES += \
i2c_smbus/i2c_smbus_i801.cpp \
HEADERS += \
dependencies/macUSPCIO/macUSPCIOAccess.h \
i2c_smbus/i2c_smbus_i801.h \
LIBS += \ LIBS += \
-L/usr/local/lib \ -L/usr/local/lib \
-L/usr/local/homebrew/lib \ -L/usr/local/homebrew/lib \
DEFINES += \
_MACOSX_X86_X64 \
} }
DISTFILES += \ DISTFILES += \

View file

@ -218,7 +218,7 @@ There have been two instances of hardware damage in OpenRGB's development and we
### SMBus Access ### SMBus Access
* SMBus/I2C devices are currently not supported on MacOS. * For Intel devices using a controller in the I801 family you have to download and install the [macUSPCIO driver](https://github.com/ShadyNawara/macUSPCIO/releases)
### USB Access ### USB Access
@ -310,7 +310,8 @@ There have been two instances of hardware damage in OpenRGB's development and we
* hueplusplus: https://github.com/enwi/hueplusplus * hueplusplus: https://github.com/enwi/hueplusplus
* httplib: https://github.com/yhirose/cpp-httplib * httplib: https://github.com/yhirose/cpp-httplib
* mdns: https://github.com/mjansson/mdns * mdns: https://github.com/mjansson/mdns
* macUSPCIO: https://github.com/ShadyNawara/macUSPCIO
## Projects Researched ## Projects Researched
While no code from these projects directly made its way into OpenRGB, these projects have been invaluable resources for protocol information. While no code from these projects directly made its way into OpenRGB, these projects have been invaluable resources for protocol information.

110
dependencies/macUSPCIO/macUSPCIOAccess.h vendored Normal file
View file

@ -0,0 +1,110 @@
//
// macUSPCIOAccess.h
// Access methods for macUSPCIO
//
// Created by Shady Nawara
// MacUSPCIO: https://github.com/ShadyNawara/macUSPCIO
//
#ifndef macUSPCIOAccess_h
#define macUSPCIOAccess_h
#include <IOKit/IOKitLib.h>
extern io_connect_t macUSPCIO_driver_connection;
inline bool InitMacUSPCIODriver()
{
if(macUSPCIO_driver_connection)
{
return true;
}
io_service_t dev = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("macUSPCIO"));
if (dev)
{
kern_return_t ret = IOServiceOpen(dev, mach_task_self(), 0, &macUSPCIO_driver_connection);
IOObjectRelease(dev);
return ret == kIOReturnSuccess;
}
return false;
}
inline bool GetMacUSPCIODriverStatus() {
if(macUSPCIO_driver_connection)
{
return true;
}
return false;
}
inline void CloseMacUSPCIODriver() {
if(macUSPCIO_driver_connection) {
IOServiceClose(macUSPCIO_driver_connection);
macUSPCIO_driver_connection = 0;
}
}
inline uint8_t ReadIoPortByte(uint16_t address)
{
if(!macUSPCIO_driver_connection)
{
return 0;
}
uint32_t outputCount = 1;
uint64_t output = 0;
uint64_t input[1] = {address};
IOConnectCallScalarMethod(macUSPCIO_driver_connection, 0, input, 1, &output, &outputCount);
return (uint8_t)output;
}
inline void WriteIoPortByte(uint16_t address, uint8_t value)
{
if(!macUSPCIO_driver_connection)
{
return;
}
uint32_t outputCount = 1;
uint64_t output = 0;
uint64_t input[2] = {address, value};
IOConnectCallScalarMethod(macUSPCIO_driver_connection, 1, input, 2, &output, &outputCount);
}
inline uint8_t ReadConfigPortByte(uint16_t address) {
if(!macUSPCIO_driver_connection)
{
return 0;
}
uint32_t outputCount = 1;
uint64_t output = 0;
uint64_t input[1] = {address};
IOConnectCallScalarMethod(macUSPCIO_driver_connection, 2, input, 1, &output, &outputCount);
return (uint8_t)output;
}
inline uint16_t ReadConfigPortWord(uint16_t address)
{
if(!macUSPCIO_driver_connection)
{
return 0;
}
uint32_t outputCount = 1;
uint64_t output = 0;
uint64_t input[1] = {address};
IOConnectCallScalarMethod(macUSPCIO_driver_connection, 3, input, 1, &output, &outputCount);
return (uint16_t)output;
}
#endif /* macUSPCIOAccess_h */

View file

@ -9,8 +9,13 @@
\*-----------------------------------------*/ \*-----------------------------------------*/
#include "i2c_smbus_i801.h" #include "i2c_smbus_i801.h"
#ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#include "OlsApi.h" #include "OlsApi.h"
#elif _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
#endif
#include "LogManager.h" #include "LogManager.h"
using namespace std::chrono_literals; using namespace std::chrono_literals;
@ -490,6 +495,7 @@ s32 i2c_smbus_i801::i2c_xfer(u8 addr, char read_write, int* size, u8* data)
} }
#include "Detector.h" #include "Detector.h"
#ifdef _WIN32
#include "wmi.h" #include "wmi.h"
bool i2c_smbus_i801_detect() bool i2c_smbus_i801_detect()
@ -558,6 +564,18 @@ bool i2c_smbus_i801_detect()
int sbv_id = (int)std::stoul(sbv_str, nullptr, 16); int sbv_id = (int)std::stoul(sbv_str, nullptr, 16);
int sbd_id = (int)std::stoul(sbd_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 = ReadPciConfigWord(pciAddress, SMBHSTCFG);
if ((host_config & SMBHSTCFG_HST_EN) == 0)
{
continue;
}
bus = new i2c_smbus_i801(); bus = new i2c_smbus_i801();
bus->pci_vendor = ven_id; bus->pci_vendor = ven_id;
bus->pci_device = dev_id; bus->pci_device = dev_id;
@ -572,5 +590,41 @@ bool i2c_smbus_i801_detect()
return(true); return(true);
} }
#elif _MACOSX_X86_X64
bool i2c_smbus_i801_detect()
{
if(!GetMacUSPCIODriverStatus())
{
LOG_INFO("macUSPCIO is not loaded, i801 I2C bus detection aborted");
return(false);
}
uint8_t host_config = ReadConfigPortByte(SMBHSTCFG);
if ((host_config & SMBHSTCFG_HST_EN) == 0)
{
LOG_INFO("i801 SMBus Disabled");
return(false);
}
i2c_smbus_interface * bus;
bus = new i2c_smbus_i801();
// addresses are referenced from: https://opensource.apple.com/source/IOPCIFamily/IOPCIFamily-146/IOKit/pci/IOPCIDevice.h.auto.html
bus->pci_vendor = ReadConfigPortWord(0x00);
bus->pci_device = ReadConfigPortWord(0x02);
bus->pci_subsystem_vendor = ReadConfigPortWord(0x2c);
bus->pci_subsystem_device = ReadConfigPortWord(0x2e);
if(!bus->pci_vendor || !bus->pci_device || !bus->pci_subsystem_vendor || !bus->pci_subsystem_device)
{
return(false);
}
sprintf(bus->device_name, "Intel(R) SMBus - %X", bus->pci_device);
((i2c_smbus_i801 *)bus)->i801_smba = ReadConfigPortWord(0x20) & 0xFFFE;
ResourceManager::get()->RegisterI2CBus(bus);
return(true);
}
#endif
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_i801_detect); REGISTER_I2C_BUS_DETECTOR(i2c_smbus_i801_detect);

View file

@ -77,6 +77,10 @@
#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR) #define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR)
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | STATUS_ERROR_FLAGS) #define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | STATUS_ERROR_FLAGS)
/* I801 Host Config */
#define SMBHSTCFG 0x040
#define SMBHSTCFG_HST_EN BIT(0)
class i2c_smbus_i801 : public i2c_smbus_interface class i2c_smbus_i801 : public i2c_smbus_interface
{ {
public: public:

View file

@ -20,6 +20,11 @@
#include <thread> #include <thread>
#include <QTranslator> #include <QTranslator>
#ifdef _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
io_connect_t macUSPCIO_driver_connection;
#endif
#include "OpenRGBDialog2.h" #include "OpenRGBDialog2.h"
#ifdef __APPLE__ #ifdef __APPLE__
@ -262,6 +267,14 @@ int main(int argc, char* argv[])
\*---------------------------------------------------------*/ \*---------------------------------------------------------*/
InstallWinRing0(); InstallWinRing0();
#endif #endif
/*---------------------------------------------------------*\
| Mac x86/x64 only - Install SMBus Driver macUSPCIO |
\*---------------------------------------------------------*/
#ifdef _MACOSX_X86_X64
InitMacUSPCIODriver();
#endif
/*---------------------------------------------------------*\ /*---------------------------------------------------------*\
| Process command line arguments before detection | | Process command line arguments before detection |
\*---------------------------------------------------------*/ \*---------------------------------------------------------*/
@ -400,15 +413,24 @@ int main(int argc, char* argv[])
{ {
if(!ResourceManager::get()->GetServer()->GetOnline()) if(!ResourceManager::get()->GetServer()->GetOnline())
{ {
#ifdef _MACOSX_X86_X64
CloseMacUSPCIODriver();
#endif
return 1; return 1;
} }
else else
{ {
WaitWhileServerOnline(ResourceManager::get()->GetServer()); WaitWhileServerOnline(ResourceManager::get()->GetServer());
#ifdef _MACOSX_X86_X64
CloseMacUSPCIODriver();
#endif
} }
} }
else else
{ {
#ifdef _MACOSX_X86_X64
CloseMacUSPCIODriver();
#endif
return 0; return 0;
} }
} }