macOS: improve IO service related code generally

This commit is contained in:
李通洲
2024-01-05 14:47:30 +08:00
parent 92a6b01133
commit b6c8649cbf
10 changed files with 108 additions and 155 deletions
+9 -20
View File
@@ -8,22 +8,19 @@
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryBattery = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
continue;
}
bool boolValue;
const char* error;
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
@@ -36,15 +33,11 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
int currentCapacity, maxCapacity;
if ((error = ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity)))
return error;
if (maxCapacity <= 0)
return "Querying MaxCapacity failed";
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
continue;
if ((error = ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity)))
return error;
if(currentCapacity <= 0)
return "Querying CurrentCapacity failed";
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity) != NULL || currentCapacity <= 0)
continue;
battery->capacity = currentCapacity * 100.0 / maxCapacity;
@@ -82,11 +75,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
else
ffDetectSmcTemps(FF_TEMP_BATTERY, &battery->temperature);
}
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
return NULL;
}
+11 -14
View File
@@ -57,38 +57,35 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
return "IOAVService is not available";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = NULL;
{
FF_CFTYPE_AUTO_RELEASE CFBooleanRef IOAVServiceUserInterfaceSupported = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("IOAVServiceUserInterfaceSupported"), kCFAllocatorDefault, kNilOptions);
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryAv = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFBooleanRef IOAVServiceUserInterfaceSupported = IORegistryEntryCreateCFProperty(entryAv, CFSTR("IOAVServiceUserInterfaceSupported"), kCFAllocatorDefault, kNilOptions);
if (IOAVServiceUserInterfaceSupported && !CFBooleanGetValue(IOAVServiceUserInterfaceSupported))
{
// IOAVServiceCreateWithService won't work
IOObjectRelease(registryEntry);
continue;
}
}
{
FF_CFTYPE_AUTO_RELEASE CFStringRef location = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("Location"), kCFAllocatorDefault, kNilOptions);
FF_CFTYPE_AUTO_RELEASE CFStringRef location = IORegistryEntryCreateCFProperty(entryAv, CFSTR("Location"), kCFAllocatorDefault, kNilOptions);
if (location && CFStringCompare(location, CFSTR("Embedded"), 0) == 0)
{
// Builtin display should be handled by DisplayServices
IOObjectRelease(registryEntry);
continue;
}
service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
if (!service) continue;
}
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
IOObjectRelease(registryEntry);
if (!service) continue;
{
uint8_t i2cIn[4] = { 0x82, 0x01, 0x10 /* luminance */ };
i2cIn[3] = 0x6e ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2];
+23 -33
View File
@@ -1,6 +1,7 @@
#include "cpu.h"
#include "common/sysctl.h"
#include "detection/temps/temps_apple.h"
#include "util/stringUtils.h"
static double detectCpuTemp(const FFstrbuf* cpuName)
{
@@ -35,44 +36,33 @@ static const char* detectFrequency(FFCPUResult* cpu)
{
// https://github.com/giampaolo/psutil/pull/2222/files
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
if (!entryDevice)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if (IORegistryEntryCreateCFProperties(entryDevice, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
return "IORegistryEntryCreateCFProperties() failed";
uint32_t pMin, eMin, aMax, pCoreLength;
if (ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength) != NULL) // pCore
return "\"voltage-states5-sram\" in \"pmgr\" is not found";
if (ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL) != NULL) // eCore
return "\"voltage-states1-sram\" in \"pmgr\" is not found";
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
io_name_t name;
if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS)
continue;
if (strcmp(name, "pmgr") != 0)
continue;
uint32_t pMin, eMin, aMax, pCoreLength;
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore
ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
CFRelease(properties);
IOObjectRelease(registryEntry);
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
IOObjectRelease(iterator);
return NULL;
}
#else
+2 -10
View File
@@ -8,22 +8,14 @@
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
static inline void wrapIoObjectRelease(io_service_t* service)
{
assert(service);
if (*service)
IOObjectRelease(*service);
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
+3 -5
View File
@@ -38,12 +38,12 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
@@ -106,8 +106,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
ffGpuDetectMetal(gpus);
return NULL;
}
+7 -18
View File
@@ -169,26 +169,15 @@ static const char* getProductNameWithHwModel(const FFstrbuf* hwModel)
const char* getProductNameWithIokit(FFstrbuf* result)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("product"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("product"));
if (!registryEntry)
return "IOServiceGetMatchingService() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
FF_CFTYPE_AUTO_RELEASE CFStringRef productName = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("product-name"), kCFAllocatorDefault, kNilOptions);
if (!productName)
return "IORegistryEntryCreateCFProperty() failed";
if (ffCfDictGetString(properties, CFSTR("product-name"), result))
break;
}
IOObjectRelease(registryEntry);
return NULL;
return ffCfStrGetString(productName, result);
}
const char* ffDetectHost(FFHostResult* host)
@@ -9,14 +9,6 @@
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
#include <IOKit/storage/nvme/NVMeSMARTLibExternal.h>
static inline void wrapIoObjectRelease(io_service_t* service)
{
assert(service);
if (*service)
IOObjectRelease(*service);
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
static inline void wrapIoDestroyPlugInInterface(IOCFPlugInInterface*** pluginInf)
{
assert(pluginInf);
@@ -49,11 +41,11 @@ static const char* detectSsdTemp(io_service_t entryPhysical, double* temp)
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
+12 -16
View File
@@ -85,12 +85,9 @@ static void smcUltostr(char *str, uint32_t val)
static const char *smcCall(io_connect_t conn, uint32_t selector, SmcKeyData_t *inputStructure, SmcKeyData_t *outputStructure)
{
size_t structureInputSize;
size_t structureOutputSize;
structureInputSize = sizeof(SmcKeyData_t);
structureOutputSize = sizeof(SmcKeyData_t);
size_t size = sizeof(SmcKeyData_t);
if (IOConnectCallStructMethod(conn, selector, inputStructure, structureInputSize, outputStructure, &structureOutputSize) != kIOReturnSuccess)
if (IOConnectCallStructMethod(conn, selector, inputStructure, size, outputStructure, &size) != kIOReturnSuccess)
return "IOConnectCallStructMethod(conn) failed";
return NULL;
}
@@ -140,17 +137,13 @@ static const char *smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcV
static const char *smcOpen(io_connect_t *conn)
{
io_iterator_t iterator;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSMC"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_object_t device = IOIteratorNext(iterator);
IOObjectRelease(iterator);
if (device == 0)
io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC"));
if (!device)
return "No SMC device found";
kern_return_t result = IOServiceOpen(device, mach_task_self(), 0, conn);
IOObjectRelease(device);
if (result != kIOReturnSuccess)
return "IOServiceOpen() failed";
@@ -290,10 +283,13 @@ static bool detectTemp(io_connect_t conn, const char *sensor, double* sum)
const char *ffDetectSmcTemps(enum FFTempType type, double *result)
{
static io_connect_t conn;
static dispatch_once_t once_control;
dispatch_once_f(&once_control, &conn, (dispatch_function_t) smcOpen);
if(!conn)
return "smcOpen() failed";
if (!conn)
{
if (smcOpen(&conn) != NULL)
conn = (io_connect_t) -1;
}
else if (conn == (io_connect_t) -1)
return "Could not open SMC connection";
uint32_t count = 0;
*result = 0;
+29 -28
View File
@@ -19,26 +19,42 @@ const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result)
return "TypeID is neither 'CFNumber' nor 'CFData'";
}
const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result)
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result)
{
if (!str)
if (!cf)
{
ffStrbufClear(result);
return NULL;
}
uint32_t length = (uint32_t)CFStringGetLength(str);
//CFString stores UTF16 characters, therefore may require larger buffer to convert to UTF8 string
ffStrbufEnsureFree(result, length * 2);
if(!CFStringGetCString(str, result->chars, result->allocated, kCFStringEncodingUTF8))
if (CFGetTypeID(cf) == CFStringGetTypeID())
{
ffStrbufEnsureFree(result, length * 4);
if(!CFStringGetCString(str, result->chars, result->allocated, kCFStringEncodingUTF8))
return "CFStringGetCString() failed";
CFStringRef cfStr = (CFStringRef)cf;
uint32_t length = (uint32_t)CFStringGetLength(cfStr);
//CFString stores UTF16 characters, therefore may require larger buffer to convert to UTF8 string
ffStrbufEnsureFree(result, length * 2);
if (!CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8))
{
ffStrbufEnsureFree(result, length * 4);
if(!CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8))
return "CFStringGetCString() failed";
}
// CFStringGetCString ensures the buffer is NUL terminated
// https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring
result->length = (uint32_t) strnlen(result->chars, (uint32_t)result->allocated);
}
// CFStringGetCString ensures the buffer is NUL terminated
// https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring
result->length = (uint32_t) strnlen(result->chars, (uint32_t)result->allocated);
else if (CFGetTypeID(cf) == CFDataGetTypeID())
{
CFDataRef cfData = (CFDataRef)cf;
uint32_t length = (uint32_t)CFDataGetLength(cfData);
ffStrbufEnsureFree(result, length + 1);
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*)result->chars);
result->length = (uint32_t)strnlen(result->chars, length);
result->chars[result->length] = '\0';
}
else
return "TypeID is neither 'CFString' nor 'CFData'";
return NULL;
}
@@ -48,22 +64,7 @@ const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* r
if(cf == NULL)
return "CFDictionaryGetValue() failed";
if(CFGetTypeID(cf) == CFStringGetTypeID())
{
return ffCfStrGetString((CFStringRef)cf, result);
}
else if(CFGetTypeID(cf) == CFDataGetTypeID())
{
CFDataRef cfData = (CFDataRef)cf;
uint32_t length = (uint32_t)CFDataGetLength(cfData);
ffStrbufEnsureFree(result, length + 1);
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*)result->chars);
result->length = (uint32_t)strnlen(result->chars, length);
result->chars[result->length] = '\0';
return NULL;
}
return "TypeID is neither 'CFString' nor 'CFData'";
return ffCfStrGetString(cf, result);
}
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result)
+10 -1
View File
@@ -5,9 +5,10 @@
#include "fastfetch.h"
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
//Return error info if failed, NULL otherwise
const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result);
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result);
const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result);
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);
@@ -29,4 +30,12 @@ static inline void cfReleaseWrapper(void* type)
#define FF_CFTYPE_AUTO_RELEASE __attribute__((__cleanup__(cfReleaseWrapper)))
static inline void wrapIoObjectRelease(io_service_t* service)
{
assert(service);
if (*service)
IOObjectRelease(*service);
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
#endif