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) {
INCLUDEPATH += \
dependencies/macUSPCIO \
/usr/local/include \
/usr/local/homebrew/include \
SOURCES += \
i2c_smbus/i2c_smbus_i801.cpp \
HEADERS += \
dependencies/macUSPCIO/macUSPCIOAccess.h \
i2c_smbus/i2c_smbus_i801.h \
LIBS += \
-L/usr/local/lib \
-L/usr/local/homebrew/lib \
DEFINES += \
_MACOSX_X86_X64 \
}
DISTFILES += \

View file

@ -218,7 +218,7 @@ There have been two instances of hardware damage in OpenRGB's development and we
### 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
@ -310,6 +310,7 @@ There have been two instances of hardware damage in OpenRGB's development and we
* hueplusplus: https://github.com/enwi/hueplusplus
* httplib: https://github.com/yhirose/cpp-httplib
* mdns: https://github.com/mjansson/mdns
* macUSPCIO: https://github.com/ShadyNawara/macUSPCIO
## Projects Researched

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"
#ifdef _WIN32
#include <Windows.h>
#include "OlsApi.h"
#elif _MACOSX_X86_X64
#include "macUSPCIOAccess.h"
#endif
#include "LogManager.h"
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"
#ifdef _WIN32
#include "wmi.h"
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 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->pci_vendor = ven_id;
bus->pci_device = dev_id;
@ -572,5 +590,41 @@ bool i2c_smbus_i801_detect()
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);

View file

@ -77,6 +77,10 @@
#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR)
#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
{
public:

View file

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