Move i2c bus detectors to their respective files and add a detector macro for i2c busses so they can be detected asynchronously. Fix WMI and DMI info.
This commit is contained in:
parent
7898e9b95d
commit
aaa2ecddc7
16 changed files with 409 additions and 438 deletions
|
|
@ -3,4 +3,5 @@
|
||||||
#include "DeviceDetector.h"
|
#include "DeviceDetector.h"
|
||||||
|
|
||||||
#define REGISTER_DETECTOR(func) static DeviceDetector device_detector_obj(func)
|
#define REGISTER_DETECTOR(func) static DeviceDetector device_detector_obj(func)
|
||||||
#define REGISTER_I2C_DETECTOR(func) static I2CDeviceDetector device_detector_obj(func)
|
#define REGISTER_I2C_DETECTOR(func) static I2CDeviceDetector device_detector_obj(func)
|
||||||
|
#define REGISTER_I2C_BUS_DETECTOR(func) static I2CBusDetector device_detector_obj(func)
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,13 @@ public:
|
||||||
{
|
{
|
||||||
ResourceManager::get()->RegisterI2CDeviceDetector(detector);
|
ResourceManager::get()->RegisterI2CDeviceDetector(detector);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class I2CBusDetector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
I2CBusDetector(I2CBusDetectorFunction detector)
|
||||||
|
{
|
||||||
|
ResourceManager::get()->RegisterI2CBusDetector(detector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
427
OpenRGB.cpp
427
OpenRGB.cpp
|
|
@ -1,427 +0,0 @@
|
||||||
/******************************************************************************************\
|
|
||||||
* *
|
|
||||||
* OpenRGB.cpp *
|
|
||||||
* *
|
|
||||||
* Functions for communicating with RGBController API devices on Windows and Linux *
|
|
||||||
* *
|
|
||||||
\******************************************************************************************/
|
|
||||||
|
|
||||||
#include "RGBController.h"
|
|
||||||
#include "i2c_smbus.h"
|
|
||||||
#include "ResourceManager.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <regex>
|
|
||||||
#include "i2c_smbus_piix4.h"
|
|
||||||
#include "i2c_smbus_i801.h"
|
|
||||||
#include "i2c_smbus_nct6775.h"
|
|
||||||
#include "i2c_smbus_nvapi.h"
|
|
||||||
#include "i2c_smbus_amdadl.h"
|
|
||||||
#include "super_io.h"
|
|
||||||
#include "wmi.h"
|
|
||||||
#else /* WIN32 */
|
|
||||||
|
|
||||||
#include "i2c_smbus_linux.h"
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#endif /* WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
/******************************************************************************************\
|
|
||||||
* *
|
|
||||||
* DetectNuvotonI2CBusses (Windows) *
|
|
||||||
* *
|
|
||||||
* Detects available Nuvoton Super IO SMBUS adapters and enumerates *
|
|
||||||
* i2c_smbus_interface objects for them *
|
|
||||||
* *
|
|
||||||
\******************************************************************************************/
|
|
||||||
|
|
||||||
void DetectNuvotonI2CBusses(std::vector<i2c_smbus_interface*> &busses)
|
|
||||||
{
|
|
||||||
i2c_smbus_interface* bus;
|
|
||||||
int sioaddr = 0x2E;
|
|
||||||
superio_enter(sioaddr);
|
|
||||||
|
|
||||||
int val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | superio_inb(sioaddr, SIO_REG_DEVID + 1);
|
|
||||||
|
|
||||||
switch (val & SIO_ID_MASK)
|
|
||||||
{
|
|
||||||
case SIO_NCT5577_ID:
|
|
||||||
case SIO_NCT6102_ID:
|
|
||||||
case SIO_NCT6793_ID:
|
|
||||||
case SIO_NCT6796_ID:
|
|
||||||
case SIO_NCT6798_ID:
|
|
||||||
bus = new i2c_smbus_nct6775();
|
|
||||||
|
|
||||||
// Set logical device register to get SMBus base address
|
|
||||||
superio_outb(sioaddr, SIO_REG_LOGDEV, SIO_LOGDEV_SMBUS);
|
|
||||||
|
|
||||||
// Get SMBus base address from configuration register
|
|
||||||
int smba = (superio_inb(sioaddr, SIO_REG_SMBA) << 8) | superio_inb(sioaddr, SIO_REG_SMBA + 1);
|
|
||||||
((i2c_smbus_nct6775*)bus)->nct6775_smba = smba;
|
|
||||||
|
|
||||||
// Set device name string
|
|
||||||
switch (val & SIO_ID_MASK)
|
|
||||||
{
|
|
||||||
case SIO_NCT5577_ID:
|
|
||||||
sprintf(bus->device_name, "Nuvoton NCT5577D SMBus at %X", smba);
|
|
||||||
break;
|
|
||||||
case SIO_NCT6102_ID:
|
|
||||||
sprintf(bus->device_name, "Nuvoton NCT6102D/NCT6106D SMBus at %X", smba);
|
|
||||||
break;
|
|
||||||
case SIO_NCT6793_ID:
|
|
||||||
sprintf(bus->device_name, "Nuvoton NCT6793D SMBus at %X", smba);
|
|
||||||
break;
|
|
||||||
case SIO_NCT6796_ID:
|
|
||||||
sprintf(bus->device_name, "Nuvoton NCT6796D SMBus at %X", smba);
|
|
||||||
break;
|
|
||||||
case SIO_NCT6798_ID:
|
|
||||||
sprintf(bus->device_name, "Nuvoton NCT6798D SMBus at %X", smba);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
busses.push_back(bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* DetectNuvotonI2CBusses() */
|
|
||||||
|
|
||||||
/******************************************************************************************\
|
|
||||||
* *
|
|
||||||
* DetectNvAPII2CBusses (Windows) *
|
|
||||||
* *
|
|
||||||
* Detects available NVidia NvAPI I2C adapters and enumerates *
|
|
||||||
* i2c_smbus_interface objects for them. Only enumerates the first bus for each GPU *
|
|
||||||
* *
|
|
||||||
\******************************************************************************************/
|
|
||||||
|
|
||||||
void DetectNvAPII2CBusses(std::vector<i2c_smbus_interface*> &busses)
|
|
||||||
{
|
|
||||||
static NV_PHYSICAL_GPU_HANDLE gpu_handles[64];
|
|
||||||
static NV_S32 gpu_count = 0;
|
|
||||||
NV_U32 device_id;
|
|
||||||
NV_U32 ext_device_id;
|
|
||||||
NV_STATUS res;
|
|
||||||
NV_U32 revision_id;
|
|
||||||
NV_U32 sub_system_id;
|
|
||||||
|
|
||||||
NV_STATUS initialize = NvAPI_Initialize();
|
|
||||||
|
|
||||||
NvAPI_EnumPhysicalGPUs(gpu_handles, &gpu_count);
|
|
||||||
|
|
||||||
for(NV_S32 gpu_idx = 0; gpu_idx < gpu_count; gpu_idx++)
|
|
||||||
{
|
|
||||||
i2c_smbus_nvapi * nvapi_bus = new i2c_smbus_nvapi(gpu_handles[gpu_idx]);
|
|
||||||
|
|
||||||
sprintf(nvapi_bus->device_name, "NVidia NvAPI I2C on GPU %d", gpu_idx);
|
|
||||||
|
|
||||||
res = NvAPI_GPU_GetPCIIdentifiers(gpu_handles[gpu_idx], &device_id, &sub_system_id, &revision_id, &ext_device_id);
|
|
||||||
|
|
||||||
if (res == 0)
|
|
||||||
{
|
|
||||||
nvapi_bus->pci_device = device_id >> 16;
|
|
||||||
nvapi_bus->pci_vendor = device_id & 0xffff;
|
|
||||||
nvapi_bus->pci_subsystem_device = sub_system_id >> 16;
|
|
||||||
nvapi_bus->pci_subsystem_vendor = sub_system_id & 0xffff;
|
|
||||||
nvapi_bus->port_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
busses.push_back(nvapi_bus);
|
|
||||||
}
|
|
||||||
} /* DetectNvAPII2CBusses() */
|
|
||||||
|
|
||||||
/******************************************************************************************\
|
|
||||||
* *
|
|
||||||
* DetectAMDADLI2CBusses (Windows) *
|
|
||||||
* *
|
|
||||||
* Detects available AMD ADL I2C adapters and enumerates *
|
|
||||||
* i2c_smbus_interface objects for them. Only enumerates Bus Nr 1 *
|
|
||||||
* *
|
|
||||||
\******************************************************************************************/
|
|
||||||
|
|
||||||
void DetectADLI2C(std::vector<i2c_smbus_interface*> &busses)
|
|
||||||
{
|
|
||||||
int adl_status;
|
|
||||||
int gpu_count = 0;
|
|
||||||
ADL_CONTEXT_HANDLE gpu_handle;
|
|
||||||
|
|
||||||
i2c_smbus_amdadl * adl_bus = new i2c_smbus_amdadl(gpu_handle);
|
|
||||||
|
|
||||||
adl_status = adl_bus->ADL_Initialize();
|
|
||||||
|
|
||||||
if(0 != adl_status)
|
|
||||||
{
|
|
||||||
printf_s("ADL Status %d \n", adl_status);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(adl_bus->device_name, "AMD ADL I2C on GPU %d", gpu_count);
|
|
||||||
busses.push_back(adl_bus);
|
|
||||||
}
|
|
||||||
} /* DetectAMDADLI2CBusses() */
|
|
||||||
|
|
||||||
/******************************************************************************************\
|
|
||||||
* *
|
|
||||||
* DetectI2CBusses (Windows) *
|
|
||||||
* *
|
|
||||||
* Detects available AMD and Intel SMBUS adapters and enumerates i2c_smbus_interface *
|
|
||||||
* objects for them *
|
|
||||||
* *
|
|
||||||
\******************************************************************************************/
|
|
||||||
|
|
||||||
void DetectI2CBusses(std::vector<i2c_smbus_interface*> &busses)
|
|
||||||
{
|
|
||||||
i2c_smbus_interface * bus;
|
|
||||||
HRESULT hres;
|
|
||||||
Wmi wmi;
|
|
||||||
wmi.init();
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
bus = new i2c_smbus_piix4();
|
|
||||||
strcpy(bus->device_name, i["Description"].c_str());
|
|
||||||
strcat(bus->device_name, " at 0x0B00");
|
|
||||||
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B00;
|
|
||||||
busses.push_back(bus);
|
|
||||||
|
|
||||||
bus = new i2c_smbus_piix4();
|
|
||||||
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B20;
|
|
||||||
strcpy(bus->device_name, i["Description"].c_str());
|
|
||||||
strcat(bus->device_name, " at 0x0B20");
|
|
||||||
busses.push_back(bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
else 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 (std::regex_search(q_res_PNPAllocatedResource[0]["Antecedent"], matches, rgx2))
|
|
||||||
{
|
|
||||||
unsigned int IORangeStart = std::stoi(matches[1].str());
|
|
||||||
|
|
||||||
bus = new i2c_smbus_i801();
|
|
||||||
strcpy(bus->device_name, i["Description"].c_str());
|
|
||||||
((i2c_smbus_i801 *)bus)->i801_smba = IORangeStart;
|
|
||||||
busses.push_back(bus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect Nuvoton Super IO SMBus adapters
|
|
||||||
DetectNuvotonI2CBusses(busses);
|
|
||||||
|
|
||||||
// Detect NVidia NvAPI I2C adapters
|
|
||||||
DetectNvAPII2CBusses(busses);
|
|
||||||
|
|
||||||
// Detect AMD ADL I2C adadpters
|
|
||||||
DetectADLI2C(busses);
|
|
||||||
|
|
||||||
} /* DetectI2CBusses() */
|
|
||||||
|
|
||||||
#else /* WIN32 */
|
|
||||||
|
|
||||||
/******************************************************************************************\
|
|
||||||
* *
|
|
||||||
* DetectI2CBusses (Linux) *
|
|
||||||
* *
|
|
||||||
* Detects available SMBUS adapters and enumerates i2c_smbus_interface objects for *
|
|
||||||
* them *
|
|
||||||
* *
|
|
||||||
\******************************************************************************************/
|
|
||||||
|
|
||||||
void DetectI2CBusses(std::vector<i2c_smbus_interface*> &busses)
|
|
||||||
{
|
|
||||||
i2c_smbus_linux * bus;
|
|
||||||
char device_string[1024];
|
|
||||||
DIR * dir;
|
|
||||||
char driver_path[512];
|
|
||||||
struct dirent * ent;
|
|
||||||
int test_fd;
|
|
||||||
char path[1024];
|
|
||||||
char buff[100];
|
|
||||||
unsigned short pci_device, pci_vendor, pci_subsystem_device, pci_subsystem_vendor;
|
|
||||||
unsigned short port_id;
|
|
||||||
bool info;
|
|
||||||
|
|
||||||
// Start looking for I2C adapters in /sys/bus/i2c/devices/
|
|
||||||
strcpy(driver_path, "/sys/bus/i2c/devices/");
|
|
||||||
dir = opendir(driver_path);
|
|
||||||
|
|
||||||
if(dir == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through all entries in i2c-adapter list
|
|
||||||
ent = readdir(dir);
|
|
||||||
while(ent != NULL)
|
|
||||||
{
|
|
||||||
if(ent->d_type == DT_DIR || ent->d_type == DT_LNK)
|
|
||||||
{
|
|
||||||
if(strncmp(ent->d_name, "i2c-", 4) == 0)
|
|
||||||
{
|
|
||||||
strcpy(device_string, driver_path);
|
|
||||||
strcat(device_string, ent->d_name);
|
|
||||||
strcat(device_string, "/name");
|
|
||||||
test_fd = open(device_string, O_RDONLY);
|
|
||||||
|
|
||||||
if(test_fd)
|
|
||||||
{
|
|
||||||
memset(device_string, 0x00, sizeof(device_string));
|
|
||||||
read(test_fd, device_string, sizeof(device_string));
|
|
||||||
device_string[strlen(device_string) - 1] = 0x00;
|
|
||||||
|
|
||||||
close(test_fd);
|
|
||||||
|
|
||||||
// For now, only get PCI information from nVidia GPUs
|
|
||||||
// PCI IDs are not currently obtained from the Nouveau driver
|
|
||||||
// and GPUs using PCI IDs for detection will not work with it.
|
|
||||||
if (sscanf(device_string, "NVIDIA i2c adapter %hu at", &port_id) == 1)
|
|
||||||
{
|
|
||||||
info = true;
|
|
||||||
|
|
||||||
// Get PCI Device
|
|
||||||
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/device");
|
|
||||||
test_fd = open(path, O_RDONLY);
|
|
||||||
if (test_fd < 0)
|
|
||||||
{
|
|
||||||
ent = readdir(dir);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
memset(buff, 0x00, sizeof(buff));
|
|
||||||
read(test_fd, buff, sizeof(buff));
|
|
||||||
buff[strlen(buff) - 1] = 0x00;
|
|
||||||
pci_device = strtoul(buff, NULL, 16);
|
|
||||||
close(test_fd);
|
|
||||||
|
|
||||||
// Get PCI Vendor
|
|
||||||
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/vendor");
|
|
||||||
test_fd = open(path, O_RDONLY);
|
|
||||||
if (test_fd < 0)
|
|
||||||
{
|
|
||||||
ent = readdir(dir);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
memset(buff, 0x00, sizeof(buff));
|
|
||||||
read(test_fd, buff, sizeof(buff));
|
|
||||||
buff[strlen(buff) - 1] = 0x00;
|
|
||||||
pci_vendor = strtoul(buff, NULL, 16);
|
|
||||||
close(test_fd);
|
|
||||||
|
|
||||||
// Get PCI Subsystem Device
|
|
||||||
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/subsystem_device");
|
|
||||||
test_fd = open(path, O_RDONLY);
|
|
||||||
if (test_fd < 0)
|
|
||||||
{
|
|
||||||
ent = readdir(dir);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
memset(buff, 0x00, sizeof(buff));
|
|
||||||
read(test_fd, buff, sizeof(buff));
|
|
||||||
buff[strlen(buff) - 1] = 0x00;
|
|
||||||
pci_subsystem_device = strtoul(buff, NULL, 16);
|
|
||||||
close(test_fd);
|
|
||||||
|
|
||||||
// Get PCI Subsystem Vendor
|
|
||||||
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/subsystem_vendor");
|
|
||||||
test_fd = open(path, O_RDONLY);
|
|
||||||
if (test_fd < 0)
|
|
||||||
{
|
|
||||||
ent = readdir(dir);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
memset(buff, 0x00, sizeof(buff));
|
|
||||||
read(test_fd, buff, sizeof(buff));
|
|
||||||
buff[strlen(buff) - 1] = 0x00;
|
|
||||||
pci_subsystem_vendor = strtoul(buff, NULL, 16);
|
|
||||||
close(test_fd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(device_string, "/dev/");
|
|
||||||
strcat(device_string, ent->d_name);
|
|
||||||
test_fd = open(device_string, O_RDWR);
|
|
||||||
|
|
||||||
if (test_fd < 0)
|
|
||||||
{
|
|
||||||
ent = readdir(dir);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bus = new i2c_smbus_linux();
|
|
||||||
strcpy(bus->device_name, device_string);
|
|
||||||
bus->handle = test_fd;
|
|
||||||
if (info) {
|
|
||||||
bus->pci_device = pci_device;
|
|
||||||
bus->pci_vendor = pci_vendor;
|
|
||||||
bus->pci_subsystem_device = pci_subsystem_device;
|
|
||||||
bus->pci_subsystem_vendor = pci_subsystem_vendor;
|
|
||||||
bus->port_id = port_id;
|
|
||||||
}
|
|
||||||
busses.push_back(bus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ent = readdir(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* DetectI2CBusses() */
|
|
||||||
|
|
||||||
#endif /* WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************************\
|
|
||||||
* *
|
|
||||||
* DetectRGBConrollers *
|
|
||||||
* *
|
|
||||||
* Detect and populate RGB Controllers vector *
|
|
||||||
* *
|
|
||||||
\******************************************************************************************/
|
|
||||||
|
|
||||||
void DetectRGBControllers(void)
|
|
||||||
{
|
|
||||||
DetectI2CBusses(ResourceManager::get()->GetI2CBusses());
|
|
||||||
|
|
||||||
ResourceManager::get()->DetectDevices();
|
|
||||||
} /* DetectRGBControllers() */
|
|
||||||
|
|
@ -229,7 +229,6 @@ SOURCES += \
|
||||||
dependencies/libe131/src/e131.c \
|
dependencies/libe131/src/e131.c \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
cli.cpp \
|
cli.cpp \
|
||||||
OpenRGB.cpp \
|
|
||||||
NetworkClient.cpp \
|
NetworkClient.cpp \
|
||||||
NetworkServer.cpp \
|
NetworkServer.cpp \
|
||||||
ProfileManager.cpp \
|
ProfileManager.cpp \
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,11 @@ std::vector<RGBController*> & ResourceManager::GetRGBControllers()
|
||||||
return rgb_controllers;
|
return rgb_controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResourceManager::RegisterI2CBusDetector(I2CBusDetectorFunction detector)
|
||||||
|
{
|
||||||
|
i2c_bus_detectors.push_back(detector);
|
||||||
|
}
|
||||||
|
|
||||||
void ResourceManager::RegisterI2CDeviceDetector(I2CDeviceDetectorFunction detector)
|
void ResourceManager::RegisterI2CDeviceDetector(I2CDeviceDetectorFunction detector)
|
||||||
{
|
{
|
||||||
i2c_device_detectors.push_back(detector);
|
i2c_device_detectors.push_back(detector);
|
||||||
|
|
@ -91,6 +96,14 @@ void ResourceManager::DetectDevicesThreadFunction()
|
||||||
{
|
{
|
||||||
unsigned int prev_count = 0;
|
unsigned int prev_count = 0;
|
||||||
|
|
||||||
|
/*-------------------------------------------------*\
|
||||||
|
| Detect i2c busses |
|
||||||
|
\*-------------------------------------------------*/
|
||||||
|
for(int i2c_bus_detector_idx = 0; i2c_bus_detector_idx < i2c_bus_detectors.size(); i2c_bus_detector_idx++)
|
||||||
|
{
|
||||||
|
i2c_bus_detectors[i2c_bus_detector_idx](busses);
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------*\
|
/*-------------------------------------------------*\
|
||||||
| Detect i2c devices |
|
| Detect i2c devices |
|
||||||
\*-------------------------------------------------*/
|
\*-------------------------------------------------*/
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "i2c_smbus.h"
|
#include "i2c_smbus.h"
|
||||||
#include "RGBController.h"
|
#include "RGBController.h"
|
||||||
|
|
||||||
|
typedef std::function<void(std::vector<i2c_smbus_interface*>&)> I2CBusDetectorFunction;
|
||||||
typedef std::function<void(std::vector<RGBController*>&)> DeviceDetectorFunction;
|
typedef std::function<void(std::vector<RGBController*>&)> DeviceDetectorFunction;
|
||||||
typedef std::function<void(std::vector<i2c_smbus_interface*>&, std::vector<RGBController*>&)> I2CDeviceDetectorFunction;
|
typedef std::function<void(std::vector<i2c_smbus_interface*>&, std::vector<RGBController*>&)> I2CDeviceDetectorFunction;
|
||||||
|
|
||||||
|
|
@ -27,6 +28,7 @@ public:
|
||||||
void RegisterRGBController(RGBController *);
|
void RegisterRGBController(RGBController *);
|
||||||
std::vector<RGBController*> & GetRGBControllers();
|
std::vector<RGBController*> & GetRGBControllers();
|
||||||
|
|
||||||
|
void RegisterI2CBusDetector (I2CBusDetectorFunction detector);
|
||||||
void RegisterDeviceDetector (DeviceDetectorFunction detector);
|
void RegisterDeviceDetector (DeviceDetectorFunction detector);
|
||||||
void RegisterI2CDeviceDetector (I2CDeviceDetectorFunction detector);
|
void RegisterI2CDeviceDetector (I2CDeviceDetectorFunction detector);
|
||||||
|
|
||||||
|
|
@ -44,6 +46,7 @@ private:
|
||||||
std::vector<i2c_smbus_interface*> busses;
|
std::vector<i2c_smbus_interface*> busses;
|
||||||
std::vector<RGBController*> rgb_controllers;
|
std::vector<RGBController*> rgb_controllers;
|
||||||
std::vector<DeviceDetectorFunction> device_detectors;
|
std::vector<DeviceDetectorFunction> device_detectors;
|
||||||
|
std::vector<I2CBusDetectorFunction> i2c_bus_detectors;
|
||||||
std::vector<I2CDeviceDetectorFunction> i2c_device_detectors;
|
std::vector<I2CDeviceDetectorFunction> i2c_device_detectors;
|
||||||
|
|
||||||
std::thread * DetectDevicesThread;
|
std::thread * DetectDevicesThread;
|
||||||
|
|
|
||||||
2
dependencies/dmiinfo.cpp
vendored
2
dependencies/dmiinfo.cpp
vendored
|
|
@ -32,7 +32,7 @@ DMIInfo::DMIInfo()
|
||||||
// Query WMI for Win32_PnPSignedDriver entries with names matching "SMBUS" or "SM BUS"
|
// Query WMI for Win32_PnPSignedDriver entries with names matching "SMBUS" or "SM BUS"
|
||||||
// These devices may be browsed under Device Manager -> System Devices
|
// These devices may be browsed under Device Manager -> System Devices
|
||||||
std::vector<QueryObj> q_res_BaseBoard;
|
std::vector<QueryObj> q_res_BaseBoard;
|
||||||
//hres = wmi.query("SELECT * FROM Win32_BaseBoard", q_res_BaseBoard);
|
hres = wmi.query("SELECT * FROM Win32_BaseBoard", q_res_BaseBoard);
|
||||||
|
|
||||||
if (hres)
|
if (hres)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -142,3 +142,27 @@ s32 i2c_smbus_amdadl::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int s
|
||||||
return (ret);
|
return (ret);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "Detector.h"
|
||||||
|
|
||||||
|
void i2c_smbus_amdadl_detect(std::vector<i2c_smbus_interface*> &busses)
|
||||||
|
{
|
||||||
|
int adl_status;
|
||||||
|
int gpu_count = 0;
|
||||||
|
ADL_CONTEXT_HANDLE gpu_handle;
|
||||||
|
|
||||||
|
i2c_smbus_amdadl * adl_bus = new i2c_smbus_amdadl(gpu_handle);
|
||||||
|
|
||||||
|
adl_status = adl_bus->ADL_Initialize();
|
||||||
|
|
||||||
|
if(0 != adl_status)
|
||||||
|
{
|
||||||
|
printf_s("ADL Status %d \n", adl_status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(adl_bus->device_name, "AMD ADL I2C on GPU %d", gpu_count);
|
||||||
|
busses.push_back(adl_bus);
|
||||||
|
}
|
||||||
|
} /* DetectAMDADLI2CBusses() */
|
||||||
|
|
||||||
|
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_amdadl_detect);
|
||||||
|
|
|
||||||
|
|
@ -482,3 +482,61 @@ s32 i2c_smbus_i801::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int siz
|
||||||
{
|
{
|
||||||
return i801_access(addr, read_write, command, size, data);
|
return i801_access(addr, read_write, command, size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Detector.h"
|
||||||
|
#include "wmi.h"
|
||||||
|
|
||||||
|
void i2c_smbus_i801_detect(std::vector<i2c_smbus_interface*> &busses)
|
||||||
|
{
|
||||||
|
i2c_smbus_interface * bus;
|
||||||
|
HRESULT hres;
|
||||||
|
Wmi wmi;
|
||||||
|
wmi.init();
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (std::regex_search(q_res_PNPAllocatedResource[0]["Antecedent"], matches, rgx2))
|
||||||
|
{
|
||||||
|
unsigned int IORangeStart = std::stoi(matches[1].str());
|
||||||
|
|
||||||
|
bus = new i2c_smbus_i801();
|
||||||
|
strcpy(bus->device_name, i["Description"].c_str());
|
||||||
|
((i2c_smbus_i801 *)bus)->i801_smba = IORangeStart;
|
||||||
|
busses.push_back(bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_i801_detect);
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,151 @@ s32 i2c_smbus_linux::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int si
|
||||||
|
|
||||||
return ioctl(handle, I2C_SMBUS, &args);
|
return ioctl(handle, I2C_SMBUS, &args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Detector.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void i2c_smbus_linux_detect(std::vector<i2c_smbus_interface*> &busses)
|
||||||
|
{
|
||||||
|
i2c_smbus_linux * bus;
|
||||||
|
char device_string[1024];
|
||||||
|
DIR * dir;
|
||||||
|
char driver_path[512];
|
||||||
|
struct dirent * ent;
|
||||||
|
int test_fd;
|
||||||
|
char path[1024];
|
||||||
|
char buff[100];
|
||||||
|
unsigned short pci_device, pci_vendor, pci_subsystem_device, pci_subsystem_vendor;
|
||||||
|
unsigned short port_id;
|
||||||
|
bool info;
|
||||||
|
|
||||||
|
// Start looking for I2C adapters in /sys/bus/i2c/devices/
|
||||||
|
strcpy(driver_path, "/sys/bus/i2c/devices/");
|
||||||
|
dir = opendir(driver_path);
|
||||||
|
|
||||||
|
if(dir == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through all entries in i2c-adapter list
|
||||||
|
ent = readdir(dir);
|
||||||
|
while(ent != NULL)
|
||||||
|
{
|
||||||
|
if(ent->d_type == DT_DIR || ent->d_type == DT_LNK)
|
||||||
|
{
|
||||||
|
if(strncmp(ent->d_name, "i2c-", 4) == 0)
|
||||||
|
{
|
||||||
|
strcpy(device_string, driver_path);
|
||||||
|
strcat(device_string, ent->d_name);
|
||||||
|
strcat(device_string, "/name");
|
||||||
|
test_fd = open(device_string, O_RDONLY);
|
||||||
|
|
||||||
|
if(test_fd)
|
||||||
|
{
|
||||||
|
memset(device_string, 0x00, sizeof(device_string));
|
||||||
|
read(test_fd, device_string, sizeof(device_string));
|
||||||
|
device_string[strlen(device_string) - 1] = 0x00;
|
||||||
|
|
||||||
|
close(test_fd);
|
||||||
|
|
||||||
|
// For now, only get PCI information from nVidia GPUs
|
||||||
|
// PCI IDs are not currently obtained from the Nouveau driver
|
||||||
|
// and GPUs using PCI IDs for detection will not work with it.
|
||||||
|
if (sscanf(device_string, "NVIDIA i2c adapter %hu at", &port_id) == 1)
|
||||||
|
{
|
||||||
|
info = true;
|
||||||
|
|
||||||
|
// Get PCI Device
|
||||||
|
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/device");
|
||||||
|
test_fd = open(path, O_RDONLY);
|
||||||
|
if (test_fd < 0)
|
||||||
|
{
|
||||||
|
ent = readdir(dir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memset(buff, 0x00, sizeof(buff));
|
||||||
|
read(test_fd, buff, sizeof(buff));
|
||||||
|
buff[strlen(buff) - 1] = 0x00;
|
||||||
|
pci_device = strtoul(buff, NULL, 16);
|
||||||
|
close(test_fd);
|
||||||
|
|
||||||
|
// Get PCI Vendor
|
||||||
|
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/vendor");
|
||||||
|
test_fd = open(path, O_RDONLY);
|
||||||
|
if (test_fd < 0)
|
||||||
|
{
|
||||||
|
ent = readdir(dir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memset(buff, 0x00, sizeof(buff));
|
||||||
|
read(test_fd, buff, sizeof(buff));
|
||||||
|
buff[strlen(buff) - 1] = 0x00;
|
||||||
|
pci_vendor = strtoul(buff, NULL, 16);
|
||||||
|
close(test_fd);
|
||||||
|
|
||||||
|
// Get PCI Subsystem Device
|
||||||
|
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/subsystem_device");
|
||||||
|
test_fd = open(path, O_RDONLY);
|
||||||
|
if (test_fd < 0)
|
||||||
|
{
|
||||||
|
ent = readdir(dir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memset(buff, 0x00, sizeof(buff));
|
||||||
|
read(test_fd, buff, sizeof(buff));
|
||||||
|
buff[strlen(buff) - 1] = 0x00;
|
||||||
|
pci_subsystem_device = strtoul(buff, NULL, 16);
|
||||||
|
close(test_fd);
|
||||||
|
|
||||||
|
// Get PCI Subsystem Vendor
|
||||||
|
snprintf(path, sizeof(path), "%s%s%s", driver_path, ent->d_name, "/device/subsystem_vendor");
|
||||||
|
test_fd = open(path, O_RDONLY);
|
||||||
|
if (test_fd < 0)
|
||||||
|
{
|
||||||
|
ent = readdir(dir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memset(buff, 0x00, sizeof(buff));
|
||||||
|
read(test_fd, buff, sizeof(buff));
|
||||||
|
buff[strlen(buff) - 1] = 0x00;
|
||||||
|
pci_subsystem_vendor = strtoul(buff, NULL, 16);
|
||||||
|
close(test_fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(device_string, "/dev/");
|
||||||
|
strcat(device_string, ent->d_name);
|
||||||
|
test_fd = open(device_string, O_RDWR);
|
||||||
|
|
||||||
|
if (test_fd < 0)
|
||||||
|
{
|
||||||
|
ent = readdir(dir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus = new i2c_smbus_linux();
|
||||||
|
strcpy(bus->device_name, device_string);
|
||||||
|
bus->handle = test_fd;
|
||||||
|
if (info) {
|
||||||
|
bus->pci_device = pci_device;
|
||||||
|
bus->pci_vendor = pci_vendor;
|
||||||
|
bus->pci_subsystem_device = pci_subsystem_device;
|
||||||
|
bus->pci_subsystem_vendor = pci_subsystem_vendor;
|
||||||
|
bus->port_id = port_id;
|
||||||
|
}
|
||||||
|
busses.push_back(bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ent = readdir(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_linux_detect);
|
||||||
|
|
|
||||||
|
|
@ -187,3 +187,56 @@ s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int
|
||||||
{
|
{
|
||||||
return nct6775_access(addr, read_write, command, size, data);
|
return nct6775_access(addr, read_write, command, size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Detector.h"
|
||||||
|
#include "super_io.h"
|
||||||
|
|
||||||
|
void i2c_smbus_nct6775_detect(std::vector<i2c_smbus_interface*> &busses)
|
||||||
|
{
|
||||||
|
i2c_smbus_interface* bus;
|
||||||
|
int sioaddr = 0x2E;
|
||||||
|
superio_enter(sioaddr);
|
||||||
|
|
||||||
|
int val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | superio_inb(sioaddr, SIO_REG_DEVID + 1);
|
||||||
|
|
||||||
|
switch (val & SIO_ID_MASK)
|
||||||
|
{
|
||||||
|
case SIO_NCT5577_ID:
|
||||||
|
case SIO_NCT6102_ID:
|
||||||
|
case SIO_NCT6793_ID:
|
||||||
|
case SIO_NCT6796_ID:
|
||||||
|
case SIO_NCT6798_ID:
|
||||||
|
bus = new i2c_smbus_nct6775();
|
||||||
|
|
||||||
|
// Set logical device register to get SMBus base address
|
||||||
|
superio_outb(sioaddr, SIO_REG_LOGDEV, SIO_LOGDEV_SMBUS);
|
||||||
|
|
||||||
|
// Get SMBus base address from configuration register
|
||||||
|
int smba = (superio_inb(sioaddr, SIO_REG_SMBA) << 8) | superio_inb(sioaddr, SIO_REG_SMBA + 1);
|
||||||
|
((i2c_smbus_nct6775*)bus)->nct6775_smba = smba;
|
||||||
|
|
||||||
|
// Set device name string
|
||||||
|
switch (val & SIO_ID_MASK)
|
||||||
|
{
|
||||||
|
case SIO_NCT5577_ID:
|
||||||
|
sprintf(bus->device_name, "Nuvoton NCT5577D SMBus at %X", smba);
|
||||||
|
break;
|
||||||
|
case SIO_NCT6102_ID:
|
||||||
|
sprintf(bus->device_name, "Nuvoton NCT6102D/NCT6106D SMBus at %X", smba);
|
||||||
|
break;
|
||||||
|
case SIO_NCT6793_ID:
|
||||||
|
sprintf(bus->device_name, "Nuvoton NCT6793D SMBus at %X", smba);
|
||||||
|
break;
|
||||||
|
case SIO_NCT6796_ID:
|
||||||
|
sprintf(bus->device_name, "Nuvoton NCT6796D SMBus at %X", smba);
|
||||||
|
break;
|
||||||
|
case SIO_NCT6798_ID:
|
||||||
|
sprintf(bus->device_name, "Nuvoton NCT6798D SMBus at %X", smba);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
busses.push_back(bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_nct6775_detect);
|
||||||
|
|
|
||||||
|
|
@ -95,3 +95,42 @@ s32 i2c_smbus_nvapi::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int si
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Detector.h"
|
||||||
|
|
||||||
|
void i2c_smbus_nvapi_detect(std::vector<i2c_smbus_interface*> &busses)
|
||||||
|
{
|
||||||
|
static NV_PHYSICAL_GPU_HANDLE gpu_handles[64];
|
||||||
|
static NV_S32 gpu_count = 0;
|
||||||
|
NV_U32 device_id;
|
||||||
|
NV_U32 ext_device_id;
|
||||||
|
NV_STATUS res;
|
||||||
|
NV_U32 revision_id;
|
||||||
|
NV_U32 sub_system_id;
|
||||||
|
|
||||||
|
NV_STATUS initialize = NvAPI_Initialize();
|
||||||
|
|
||||||
|
NvAPI_EnumPhysicalGPUs(gpu_handles, &gpu_count);
|
||||||
|
|
||||||
|
for(NV_S32 gpu_idx = 0; gpu_idx < gpu_count; gpu_idx++)
|
||||||
|
{
|
||||||
|
i2c_smbus_nvapi * nvapi_bus = new i2c_smbus_nvapi(gpu_handles[gpu_idx]);
|
||||||
|
|
||||||
|
sprintf(nvapi_bus->device_name, "NVidia NvAPI I2C on GPU %d", gpu_idx);
|
||||||
|
|
||||||
|
res = NvAPI_GPU_GetPCIIdentifiers(gpu_handles[gpu_idx], &device_id, &sub_system_id, &revision_id, &ext_device_id);
|
||||||
|
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
nvapi_bus->pci_device = device_id >> 16;
|
||||||
|
nvapi_bus->pci_vendor = device_id & 0xffff;
|
||||||
|
nvapi_bus->pci_subsystem_device = sub_system_id >> 16;
|
||||||
|
nvapi_bus->pci_subsystem_vendor = sub_system_id & 0xffff;
|
||||||
|
nvapi_bus->port_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
busses.push_back(nvapi_bus);
|
||||||
|
}
|
||||||
|
} /* DetectNvAPII2CBusses() */
|
||||||
|
|
||||||
|
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_nvapi_detect);
|
||||||
|
|
|
||||||
|
|
@ -176,3 +176,48 @@ s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int si
|
||||||
{
|
{
|
||||||
return piix4_access(addr, read_write, command, size, data);
|
return piix4_access(addr, read_write, command, size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Detector.h"
|
||||||
|
#include "wmi.h"
|
||||||
|
|
||||||
|
void i2c_smbus_piix4_detect(std::vector<i2c_smbus_interface*> &busses)
|
||||||
|
{
|
||||||
|
i2c_smbus_interface * bus;
|
||||||
|
HRESULT hres;
|
||||||
|
Wmi wmi;
|
||||||
|
wmi.init();
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
bus = new i2c_smbus_piix4();
|
||||||
|
strcpy(bus->device_name, i["Description"].c_str());
|
||||||
|
strcat(bus->device_name, " at 0x0B00");
|
||||||
|
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B00;
|
||||||
|
busses.push_back(bus);
|
||||||
|
|
||||||
|
bus = new i2c_smbus_piix4();
|
||||||
|
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B20;
|
||||||
|
strcpy(bus->device_name, i["Description"].c_str());
|
||||||
|
strcat(bus->device_name, " at 0x0B20");
|
||||||
|
busses.push_back(bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_piix4_detect);
|
||||||
|
|
|
||||||
2
main.cpp
2
main.cpp
|
|
@ -154,7 +154,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
if(!AttemptLocalConnection(rgb_controllers))
|
if(!AttemptLocalConnection(rgb_controllers))
|
||||||
{
|
{
|
||||||
DetectRGBControllers();
|
ResourceManager::get()->DetectDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
profile_manager.LoadSizeFromProfile("sizes.ors");
|
profile_manager.LoadSizeFromProfile("sizes.ors");
|
||||||
|
|
|
||||||
14
wmi/wmi.cpp
14
wmi/wmi.cpp
|
|
@ -1,5 +1,8 @@
|
||||||
#include "wmi.h"
|
#include "wmi.h"
|
||||||
|
|
||||||
|
IWbemLocator* Wmi::pLoc = nullptr;
|
||||||
|
IWbemServices* Wmi::pSvc = nullptr;
|
||||||
|
|
||||||
// Taken from https://stackoverflow.com/questions/215963/
|
// Taken from https://stackoverflow.com/questions/215963/
|
||||||
// Convert a wide Unicode string to an UTF8 string
|
// Convert a wide Unicode string to an UTF8 string
|
||||||
std::string utf8_encode(const std::wstring& wstr)
|
std::string utf8_encode(const std::wstring& wstr)
|
||||||
|
|
@ -32,22 +35,25 @@ bool isMatch(const std::string& value, const std::regex& re)
|
||||||
return std::regex_match(value, re);
|
return std::regex_match(value, re);
|
||||||
}
|
}
|
||||||
|
|
||||||
Wmi::Wmi() : pLoc(nullptr), pSvc(nullptr)
|
Wmi::Wmi()
|
||||||
{
|
{
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Wmi::~Wmi()
|
Wmi::~Wmi()
|
||||||
{
|
{
|
||||||
//pSvc->Release();
|
|
||||||
//pLoc->Release();
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Wmi::init()
|
HRESULT Wmi::init()
|
||||||
{
|
{
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
|
if(pLoc != nullptr && pSvc != nullptr)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize COM. ------------------------------------------
|
// Initialize COM. ------------------------------------------
|
||||||
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||||
if (FAILED(hres))
|
if (FAILED(hres))
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,6 @@ public:
|
||||||
const AdditionalFilters* filters = nullptr);
|
const AdditionalFilters* filters = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IWbemLocator *pLoc = nullptr;
|
static IWbemLocator *pLoc;
|
||||||
IWbemServices *pSvc= nullptr;
|
static IWbemServices *pSvc;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue