Chore: run clang-format

```bash
find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) ! -path "src/3rdparty/*" -print0 | xargs -0 clang-format -i
```
This commit is contained in:
李通洲
2026-03-29 09:28:49 +08:00
parent cdd4cee968
commit e0eba8ce21
690 changed files with 28093 additions and 30062 deletions
+1 -2
View File
@@ -5,8 +5,7 @@
#define FF_BATTERY_TEMP_UNSET (-DBL_MAX)
typedef struct FFBatteryResult
{
typedef struct FFBatteryResult {
FFstrbuf manufacturer;
FFstrbuf manufactureDate;
FFstrbuf modelName;
+56 -49
View File
@@ -7,31 +7,29 @@
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
#define FF_TERMUX_API_PARAM "BatteryStatus"
static inline void wrapYyjsonFree(yyjson_doc** doc)
{
static inline void wrapYyjsonFree(yyjson_doc** doc) {
assert(doc);
if (*doc)
if (*doc) {
yyjson_doc_free(*doc);
}
}
static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
{
static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if(ffProcessAppendStdOut(&buffer, (char* const[]){
FF_TERMUX_API_PATH,
FF_TERMUX_API_PARAM,
NULL
}))
if (ffProcessAppendStdOut(&buffer, (char* const[]) {FF_TERMUX_API_PATH, FF_TERMUX_API_PARAM, NULL})) {
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
}
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(buffer.chars, buffer.length, 0, NULL, NULL);
if (!doc)
if (!doc) {
return "Failed to parse battery info";
}
yyjson_val* root = yyjson_doc_get_root(doc);
if (!yyjson_is_obj(root))
if (!yyjson_is_obj(root)) {
return "Battery info result is not a JSON object";
}
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
@@ -46,50 +44,54 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage"));
const char* acStatus = yyjson_get_str(yyjson_obj_get(root, "plugged"));
if (acStatus)
{
if (ffStrEquals(acStatus, "PLUGGED_AC"))
if (acStatus) {
if (ffStrEquals(acStatus, "PLUGGED_AC")) {
ffStrbufAppendS(&battery->status, "AC Connected, ");
else if (ffStrEquals(acStatus, "PLUGGED_USB"))
} else if (ffStrEquals(acStatus, "PLUGGED_USB")) {
ffStrbufAppendS(&battery->status, "USB Connected, ");
else if (ffStrEquals(acStatus, "PLUGGED_WIRELESS"))
} else if (ffStrEquals(acStatus, "PLUGGED_WIRELESS")) {
ffStrbufAppendS(&battery->status, "Wireless Connected, ");
}
}
const char* status = yyjson_get_str(yyjson_obj_get(root, "status"));
if (status)
{
if (ffStrEquals(status, "CHARGING"))
if (status) {
if (ffStrEquals(status, "CHARGING")) {
ffStrbufAppendS(&battery->status, "Charging");
else if (ffStrEquals(status, "DISCHARGING"))
} else if (ffStrEquals(status, "DISCHARGING")) {
ffStrbufAppendS(&battery->status, "Discharging");
}
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
if(options->temp)
if (options->temp) {
battery->temperature = yyjson_get_num(yyjson_obj_get(root, "temperature"));
}
return NULL;
}
static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
{
static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) {
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if (ffProcessAppendStdOut(&buf, (char* []) {
"/system/bin/dumpsys",
"battery",
NULL,
}) != NULL || buf.length == 0)
if (ffProcessAppendStdOut(&buf, (char*[]) {
"/system/bin/dumpsys",
"battery",
NULL,
}) != NULL ||
buf.length == 0) {
return "Executing `/system/bin/dumpsys battery` failed"; // Only works in `adb shell`, or when rooted
}
if (!ffStrbufStartsWithS(&buf, "Current Battery Service state:\n"))
if (!ffStrbufStartsWithS(&buf, "Current Battery Service state:\n")) {
return "Invalid `/system/bin/dumpsys battery` result";
}
const char* start = buf.chars + strlen("Current Battery Service state:\n");
FF_STRBUF_AUTO_DESTROY temp = ffStrbufCreate();
if (!ffParsePropLines(start, "present: ", &temp) || !ffStrbufEqualS(&temp, "true"))
if (!ffParsePropLines(start, "present: ", &temp) || !ffStrbufEqualS(&temp, "true")) {
return NULL;
}
ffStrbufClear(&temp);
FFBatteryResult* battery = ffListAdd(results);
@@ -104,45 +106,50 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true")) {
ffStrbufAppendS(&battery->status, "AC powered");
}
ffStrbufClear(&temp);
if (ffParsePropLines(start, "USB powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
{
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
if (ffParsePropLines(start, "USB powered: ", &temp) && ffStrbufEqualS(&temp, "true")) {
if (battery->status.length) {
ffStrbufAppendS(&battery->status, ", ");
}
ffStrbufAppendS(&battery->status, "USB powered");
}
ffStrbufClear(&temp);
if (ffParsePropLines(start, "Wireless powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
{
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
if (ffParsePropLines(start, "Wireless powered: ", &temp) && ffStrbufEqualS(&temp, "true")) {
if (battery->status.length) {
ffStrbufAppendS(&battery->status, ", ");
}
ffStrbufAppendS(&battery->status, "Wireless powered");
}
ffStrbufClear(&temp);
{
double level = 0, scale = 0;
if (ffParsePropLines(start, "level: ", &temp))
if (ffParsePropLines(start, "level: ", &temp)) {
level = ffStrbufToDouble(&temp, -DBL_MAX);
}
ffStrbufClear(&temp);
if (ffParsePropLines(start, "scale: ", &temp))
if (ffParsePropLines(start, "scale: ", &temp)) {
scale = ffStrbufToDouble(&temp, -DBL_MAX);
}
ffStrbufClear(&temp);
if (level > 0 && scale > 0)
if (level > 0 && scale > 0) {
battery->capacity = level * 100 / scale;
}
}
if(options->temp)
{
if (ffParsePropLines(start, "temperature: ", &temp))
{
if (options->temp) {
if (ffParsePropLines(start, "temperature: ", &temp)) {
battery->temperature = ffStrbufToDouble(&temp, FF_BATTERY_TEMP_UNSET);
if (battery->temperature != FF_BATTERY_TEMP_UNSET)
if (battery->temperature != FF_BATTERY_TEMP_UNSET) {
battery->temperature /= 10.0; // Android returns temperature in tenths of a degree
}
}
ffStrbufClear(&temp);
}
@@ -152,10 +159,10 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
return NULL;
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
const char* error = parseTermuxApi(options, results);
if (error && parseDumpsys(options, results) == NULL)
if (error && parseDumpsys(options, results) == NULL) {
return NULL;
}
return error;
}
+33 -34
View File
@@ -6,27 +6,29 @@
#include <IOKit/IOKitLib.h>
#include <IOKit/pwr_mgt/IOPM.h>
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess) {
return "IOServiceGetMatchingServices() failed";
}
io_registry_entry_t registryEntry;
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
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(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) {
continue;
}
int currentCapacity, maxCapacity;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0) {
continue;
}
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity) != NULL || currentCapacity <= 0)
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity) != NULL || currentCapacity <= 0) {
continue;
}
bool boolValue;
@@ -44,13 +46,14 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
ffCfDictGetString(properties, CFSTR(kIOPMPSSerialKey), &battery->serial);
ffCfDictGetString(properties, CFSTR(kIOPMPSManufacturerKey), &battery->manufacturer);
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
{
if (!battery->manufacturer.length)
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue) {
if (!battery->manufacturer.length) {
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
}
ffStrbufAppendS(&battery->technology, "Lithium");
if (!battery->modelName.length)
if (!battery->modelName.length) {
ffStrbufAppendS(&battery->modelName, "Built-in");
}
}
int32_t cycleCount = 0;
@@ -58,43 +61,39 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
battery->cycleCount = cycleCount < 0 ? 0 : (uint32_t) cycleCount;
battery->timeRemaining = -1;
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) == NULL)
{
if (boolValue)
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) == NULL) {
if (boolValue) {
ffStrbufAppendS(&battery->status, "AC connected, ");
else
{
} else {
ffStrbufAppendS(&battery->status, "Discharging, ");
ffCfDictGetInt(properties, CFSTR("AvgTimeToEmpty"), &battery->timeRemaining); // in minutes
if (battery->timeRemaining < 0 || battery->timeRemaining >= 0xFFFF)
if (battery->timeRemaining < 0 || battery->timeRemaining >= 0xFFFF) {
battery->timeRemaining = -1;
else
} else {
battery->timeRemaining *= 60;
}
}
}
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) == NULL && boolValue)
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) == NULL && boolValue) {
ffStrbufAppendS(&battery->status, "Charging, ");
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) == NULL && boolValue)
}
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) == NULL && boolValue) {
ffStrbufAppendS(&battery->status, "Critical, ");
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
int sbdsManufactureDate = 0;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSManufactureDateKey), &sbdsManufactureDate) == NULL)
{
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSManufactureDateKey), &sbdsManufactureDate) == NULL) {
int day = sbdsManufactureDate & 0b11111;
int month = (sbdsManufactureDate >> 5) & 0b1111;
int year = (sbdsManufactureDate >> 9) + 1800;
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
else
{
} else {
CFDictionaryRef batteryData;
if (ffCfDictGetDict(properties, CFSTR("BatteryData"), &batteryData) == NULL)
{
if (ffCfDictGetDict(properties, CFSTR("BatteryData"), &batteryData) == NULL) {
char manufactureDate[sizeof(uint64_t)];
if (ffCfDictGetInt64(batteryData, CFSTR(kIOPMPSManufactureDateKey), (int64_t*) manufactureDate) == NULL)
{
if (ffCfDictGetInt64(batteryData, CFSTR(kIOPMPSManufactureDateKey), (int64_t*) manufactureDate) == NULL) {
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
@@ -104,13 +103,13 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
}
}
if (options->temp)
{
if (options->temp) {
int64_t temp;
if (!ffCfDictGetInt64(properties, CFSTR(kIOPMPSBatteryTemperatureKey), &temp))
if (!ffCfDictGetInt64(properties, CFSTR(kIOPMPSBatteryTemperatureKey), &temp)) {
battery->temperature = (double) temp / 10 - 273.15;
else
} else {
ffDetectSmcTemps(FF_TEMP_BATTERY, &battery->temperature);
}
}
}
+29 -32
View File
@@ -8,29 +8,31 @@
#include <sys/fcntl.h>
#include <unistd.h>
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
//https://www.freebsd.org/cgi/man.cgi?acpi_battery(4)
//https://gitlab.xfce.org/panel-plugins/xfce4-battery-plugin/-/blob/master/panel-plugin/libacpi.c
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results) {
// https://www.freebsd.org/cgi/man.cgi?acpi_battery(4)
// https://gitlab.xfce.org/panel-plugins/xfce4-battery-plugin/-/blob/master/panel-plugin/libacpi.c
int units = ffSysctlGetInt("hw.acpi.battery.units", -100);
if (units < 0)
if (units < 0) {
return "sysctlbyname(\"hw.acpi.battery.units\") failed";
}
if(units == 0)
if (units == 0) {
return NULL;
}
FF_AUTO_CLOSE_FD int acpifd = open("/dev/acpi", O_RDONLY | O_CLOEXEC);
if(acpifd < 0)
if (acpifd < 0) {
return "open(\"/dev/acpi\", O_RDONLY | O_CLOEXEC) failed";
}
for(int i = 0; i < units; ++i)
{
for (int i = 0; i < units; ++i) {
union acpi_battery_ioctl_arg battio;
battio.unit = i;
if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT))
if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT)) {
continue;
}
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
@@ -42,54 +44,49 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->timeRemaining = -1;
if (battio.battinfo.min > 0)
if (battio.battinfo.min > 0) {
battery->timeRemaining = battio.battinfo.min * 60;
battery->capacity = battio.battinfo.cap;
if(battio.battinfo.state == ACPI_BATT_STAT_INVALID)
{
ffStrbufAppendS(&battery->status, "Unknown, ");
}
else
{
if(battio.battinfo.state & ACPI_BATT_STAT_DISCHARG)
battery->capacity = battio.battinfo.cap;
if (battio.battinfo.state == ACPI_BATT_STAT_INVALID) {
ffStrbufAppendS(&battery->status, "Unknown, ");
} else {
if (battio.battinfo.state & ACPI_BATT_STAT_DISCHARG) {
ffStrbufAppendS(&battery->status, "Discharging, ");
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
} else if (battio.battinfo.state & ACPI_BATT_STAT_CHARGING) {
ffStrbufAppendS(&battery->status, "Charging, ");
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
}
if (battio.battinfo.state & ACPI_BATT_STAT_CRITICAL) {
ffStrbufAppendS(&battery->status, "Critical, ");
}
}
int acadStatus;
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus)
{
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus) {
ffStrbufAppendS(&battery->status, "AC Connected");
}
else
{
} else {
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
#ifdef ACPIIO_BATT_GET_BIX
#ifdef ACPIIO_BATT_GET_BIX
battio.unit = i;
if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) >= 0)
{
if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) >= 0) {
ffStrbufAppendS(&battery->manufacturer, battio.bix.oeminfo);
ffStrbufAppendS(&battery->modelName, battio.bix.model);
ffStrbufAppendS(&battery->technology, battio.bix.type);
ffStrbufAppendS(&battery->serial, battio.bix.serial);
battery->cycleCount = battio.bix.cycles;
}
#elif defined(ACPIIO_BATT_GET_BIF)
#elif defined(ACPIIO_BATT_GET_BIF)
battio.unit = i;
if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) >= 0)
{
if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) >= 0) {
ffStrbufAppendS(&battery->manufacturer, battio.bif.oeminfo);
ffStrbufAppendS(&battery->modelName, battio.bif.model);
ffStrbufAppendS(&battery->technology, battio.bif.type);
ffStrbufAppendS(&battery->serial, battio.bif.serial);
}
#endif
#endif
}
return NULL;
}
+27 -17
View File
@@ -6,22 +6,26 @@
#include <sys/ioctl.h>
#include <fcntl.h>
const char* parseBattery(int dfd, const char* battId, FFlist* results)
{
const char* parseBattery(int dfd, const char* battId, FFlist* results) {
FF_AUTO_CLOSE_FD int fd = openat(dfd, battId, O_RDWR);
if (fd < 0) return "openat() failed";
if (fd < 0) {
return "openat() failed";
}
acpi_battery_info basic = {};
if (ioctl(fd, GET_BATTERY_INFO, &basic, sizeof(basic)) != 0)
if (ioctl(fd, GET_BATTERY_INFO, &basic, sizeof(basic)) != 0) {
return "ioctl(GET_BATTERY_INFO) failed";
}
acpi_extended_battery_info extended = {};
if (ioctl(fd, GET_EXTENDED_BATTERY_INFO, &extended, sizeof(extended)) != 0)
if (ioctl(fd, GET_EXTENDED_BATTERY_INFO, &extended, sizeof(extended)) != 0) {
return "ioctl(GET_EXTENDED_BATTERY_INFO) failed";
}
if (extended.last_full_charge == (uint32)-1)
if (extended.last_full_charge == (uint32) -1) {
return "Skipped";
}
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(results);
ffStrbufInitS(&battery->modelName, extended.model_number);
ffStrbufInitS(&battery->manufacturer, extended.oem_info);
ffStrbufInit(&battery->manufactureDate);
@@ -33,29 +37,35 @@ const char* parseBattery(int dfd, const char* battId, FFlist* results)
battery->timeRemaining = -1;
battery->capacity = (double) basic.capacity * 100. / (double) extended.last_full_charge;
if (basic.state & BATTERY_DISCHARGING)
if (basic.state & BATTERY_DISCHARGING) {
ffStrbufAppendS(&battery->status, "Discharging, ");
if (basic.state & BATTERY_CHARGING)
}
if (basic.state & BATTERY_CHARGING) {
ffStrbufAppendS(&battery->status, "Charging, ");
if (basic.state & BATTERY_CRITICAL_STATE)
}
if (basic.state & BATTERY_CRITICAL_STATE) {
ffStrbufAppendS(&battery->status, "Critical, ");
if (basic.state & BATTERY_NOT_CHARGING)
}
if (basic.state & BATTERY_NOT_CHARGING) {
ffStrbufAppendS(&battery->status, "AC Connected, ");
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
return NULL;
}
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results) {
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/power/acpi_battery/");
if (!dir) return "opendir(/dev/power/acpi_battery) failed";
if (!dir) {
return "opendir(/dev/power/acpi_battery) failed";
}
struct dirent* entry;
while ((entry = readdir(dir)))
{
if (entry->d_name[0] == '.') continue;
while ((entry = readdir(dir))) {
if (entry->d_name[0] == '.') {
continue;
}
parseBattery(dirfd(dir), entry->d_name, results);
}
+72 -70
View File
@@ -8,142 +8,143 @@
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
static bool checkAc(const char* id, FFstrbuf* tmpBuffer)
{
if (ffStrStartsWith(id, "BAT"))
static bool checkAc(const char* id, FFstrbuf* tmpBuffer) {
if (ffStrStartsWith(id, "BAT")) {
ffStrbufSetS(tmpBuffer, "/sys/class/power_supply/ADP1/online");
else if (ffStrStartsWith(id, "macsmc-battery"))
} else if (ffStrStartsWith(id, "macsmc-battery")) {
ffStrbufSetS(tmpBuffer, "/sys/class/power_supply/macsmc-ac/online");
else
} else {
ffStrbufClear(tmpBuffer);
}
char online = '\0';
return ffReadFileData(tmpBuffer->chars, 1, &online) == 1 && online == '1';
}
static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFlist* results)
{
static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFlist* results) {
FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate();
// type must exist and be "Battery"
if (!ffReadFileBufferRelative(dfd, "type", &tmpBuffer))
if (!ffReadFileBufferRelative(dfd, "type", &tmpBuffer)) {
return;
}
ffStrbufTrimRightSpace(&tmpBuffer);
if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Battery"))
if (!ffStrbufIgnCaseEqualS(&tmpBuffer, "Battery")) {
return;
}
// scope may not exist or must not be "Device"
if (ffReadFileBufferRelative(dfd, "scope", &tmpBuffer))
if (ffReadFileBufferRelative(dfd, "scope", &tmpBuffer)) {
ffStrbufTrimRightSpace(&tmpBuffer);
}
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
if (ffStrbufIgnCaseEqualS(&tmpBuffer, "Device")) {
return;
}
// capacity must exist and be not empty
// This is expensive in my laptop
if (!ffReadFileBufferRelative(dfd, "capacity", &tmpBuffer))
if (!ffReadFileBufferRelative(dfd, "capacity", &tmpBuffer)) {
return;
}
FFBatteryResult* result = ffListAdd(results);
result->capacity = ffStrbufToDouble(&tmpBuffer, 0);
//At this point, we have a battery. Try to get as much values as possible.
// At this point, we have a battery. Try to get as much values as possible.
ffStrbufInit(&result->manufacturer);
if (ffReadFileBufferRelative(dfd, "manufacturer", &result->manufacturer))
if (ffReadFileBufferRelative(dfd, "manufacturer", &result->manufacturer)) {
ffStrbufTrimRightSpace(&result->manufacturer);
else if (ffStrEquals(id, "macsmc-battery")) // asahi
} else if (ffStrEquals(id, "macsmc-battery")) { // asahi
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
}
ffStrbufInit(&result->modelName);
if (ffReadFileBufferRelative(dfd, "model_name", &result->modelName))
if (ffReadFileBufferRelative(dfd, "model_name", &result->modelName)) {
ffStrbufTrimRightSpace(&result->modelName);
}
ffStrbufInit(&result->technology);
if (ffReadFileBufferRelative(dfd, "technology", &result->technology))
if (ffReadFileBufferRelative(dfd, "technology", &result->technology)) {
ffStrbufTrimRightSpace(&result->technology);
}
ffStrbufInit(&result->status);
if (ffReadFileBufferRelative(dfd, "status", &result->status))
if (ffReadFileBufferRelative(dfd, "status", &result->status)) {
ffStrbufTrimRightSpace(&result->status);
}
// Unknown, Charging, Discharging, Not charging, Full
result->timeRemaining = -1;
if (ffStrbufEqualS(&result->status, "Discharging"))
{
if (ffReadFileBufferRelative(dfd, "time_to_empty_now", &tmpBuffer))
if (ffStrbufEqualS(&result->status, "Discharging")) {
if (ffReadFileBufferRelative(dfd, "time_to_empty_now", &tmpBuffer)) {
result->timeRemaining = (int32_t) ffStrbufToSInt(&tmpBuffer, 0);
else
{
if (ffReadFileBufferRelative(dfd, "charge_now", &tmpBuffer))
{
} else {
if (ffReadFileBufferRelative(dfd, "charge_now", &tmpBuffer)) {
int64_t chargeNow = ffStrbufToSInt(&tmpBuffer, 0);
if (chargeNow > 0)
{
if (ffReadFileBufferRelative(dfd, "current_now", &tmpBuffer))
{
if (chargeNow > 0) {
if (ffReadFileBufferRelative(dfd, "current_now", &tmpBuffer)) {
int64_t currentNow = ffStrbufToSInt(&tmpBuffer, INT64_MIN);
if (currentNow < 0) currentNow = -currentNow;
if (currentNow > 0)
if (currentNow < 0) {
currentNow = -currentNow;
}
if (currentNow > 0) {
result->timeRemaining = (int32_t) ((chargeNow * 3600) / currentNow);
}
}
}
}
}
if (checkAc(id, &tmpBuffer))
if (checkAc(id, &tmpBuffer)) {
ffStrbufAppendS(&result->status, ", AC Connected");
}
else if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full"))
}
} else if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full")) {
ffStrbufSetStatic(&result->status, "AC Connected");
else if (ffStrbufEqualS(&result->status, "Charging"))
} else if (ffStrbufEqualS(&result->status, "Charging")) {
ffStrbufAppendS(&result->status, ", AC Connected");
else if (ffStrbufEqualS(&result->status, "Unknown"))
{
} else if (ffStrbufEqualS(&result->status, "Unknown")) {
ffStrbufClear(&result->status);
if (checkAc(id, &tmpBuffer))
if (checkAc(id, &tmpBuffer)) {
ffStrbufAppendS(&result->status, "AC Connected");
}
}
if (ffReadFileBufferRelative(dfd, "capacity_level", &tmpBuffer))
{
if (ffReadFileBufferRelative(dfd, "capacity_level", &tmpBuffer)) {
ffStrbufTrimRightSpace(&tmpBuffer);
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
{
if (result->status.length)
if (ffStrbufEqualS(&tmpBuffer, "Critical")) {
if (result->status.length) {
ffStrbufAppendS(&result->status, ", Critical");
else
} else {
ffStrbufSetStatic(&result->status, "Critical");
}
}
}
ffStrbufInit(&result->serial);
if (ffReadFileBufferRelative(dfd, "serial_number", &result->serial))
if (ffReadFileBufferRelative(dfd, "serial_number", &result->serial)) {
ffStrbufTrimRightSpace(&result->serial);
}
if (ffReadFileBufferRelative(dfd, "cycle_count", &tmpBuffer))
{
if (ffReadFileBufferRelative(dfd, "cycle_count", &tmpBuffer)) {
int64_t cycleCount = ffStrbufToSInt(&tmpBuffer, 0);
result->cycleCount = cycleCount < 0 || cycleCount > UINT32_MAX ? 0 : (uint32_t) cycleCount;
}
ffStrbufInit(&result->manufactureDate);
if (ffReadFileBufferRelative(dfd, "manufacture_year", &tmpBuffer))
{
if (ffReadFileBufferRelative(dfd, "manufacture_year", &tmpBuffer)) {
int year = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (year > 0)
{
if (ffReadFileBufferRelative(dfd, "manufacture_month", &tmpBuffer))
{
if (year > 0) {
if (ffReadFileBufferRelative(dfd, "manufacture_month", &tmpBuffer)) {
int month = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (month > 0)
{
if (ffReadFileBufferRelative(dfd, "manufacture_day", &tmpBuffer))
{
if (month > 0) {
if (ffReadFileBufferRelative(dfd, "manufacture_day", &tmpBuffer)) {
int day = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (day > 0)
if (day > 0) {
ffStrbufSetF(&result->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
}
}
}
@@ -151,31 +152,32 @@ static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl
}
result->temperature = FF_BATTERY_TEMP_UNSET;
if (options->temp)
{
if (ffReadFileBufferRelative(dfd, "temp", &tmpBuffer))
{
if (options->temp) {
if (ffReadFileBufferRelative(dfd, "temp", &tmpBuffer)) {
result->temperature = ffStrbufToDouble(&tmpBuffer, FF_BATTERY_TEMP_UNSET);
if (result->temperature != FF_BATTERY_TEMP_UNSET)
if (result->temperature != FF_BATTERY_TEMP_UNSET) {
result->temperature /= 10;
}
}
}
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/power_supply/");
if(dirp == NULL)
if (dirp == NULL) {
return "opendir(\"/sys/class/power_supply/\") == NULL";
}
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
FF_AUTO_CLOSE_FD int dfd = openat(dirfd(dirp), entry->d_name, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
if (dfd > 0) parseBattery(dfd, entry->d_name, options, results);
if (dfd > 0) {
parseBattery(dfd, entry->d_name, options, results);
}
}
return NULL;
+33 -33
View File
@@ -14,67 +14,66 @@
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results) {
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
if (fd < 0) {
return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
}
prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0) {
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
}
bool acConnected = false;
{
prop_array_t acad = prop_dictionary_get(root, "acpiacad0");
if (acad)
{
if (acad) {
prop_dictionary_t dict = prop_array_get(acad, 0);
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &acConnected);
}
}
prop_object_iterator_t itKey = prop_dictionary_iterator(root);
for (prop_dictionary_keysym_t key; (key = prop_object_iterator_next(itKey)) != NULL; )
{
if (!ffStrStartsWith(prop_dictionary_keysym_value(key), "acpibat")) continue;
for (prop_dictionary_keysym_t key; (key = prop_object_iterator_next(itKey)) != NULL;) {
if (!ffStrStartsWith(prop_dictionary_keysym_value(key), "acpibat")) {
continue;
}
prop_array_t bat = prop_dictionary_get_keysym(root, key);
uint32_t max = 0, curr = 0, dischargeRate = 0;
bool charging = false, critical = false;
prop_object_iterator_t iter = prop_array_iterator(bat);
for (prop_dictionary_t dict; (dict = prop_object_iterator_next(iter)) != NULL;)
{
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
for (prop_dictionary_t dict; (dict = prop_object_iterator_next(iter)) != NULL;) {
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY) {
continue;
}
const char* desc = NULL;
if (!prop_dictionary_get_string(dict, "description", &desc))
if (!prop_dictionary_get_string(dict, "description", &desc)) {
continue;
}
if (ffStrEquals(desc, "present"))
{
if (ffStrEquals(desc, "present")) {
int value = 0;
if (prop_dictionary_get_int(dict, "cur-value", &value) && value == 0)
if (prop_dictionary_get_int(dict, "cur-value", &value) && value == 0) {
continue;
}
else if (ffStrEquals(desc, "charging"))
{
}
} else if (ffStrEquals(desc, "charging")) {
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &charging);
}
else if (ffStrEquals(desc, "charge"))
{
} else if (ffStrEquals(desc, "charge")) {
prop_dictionary_get_uint32(dict, "max-value", &max);
prop_dictionary_get_uint32(dict, "cur-value", &curr);
const char* state = NULL;
if (prop_dictionary_get_string(dict, "state", &state) && ffStrEquals(state, "critical"))
if (prop_dictionary_get_string(dict, "state", &state) && ffStrEquals(state, "critical")) {
critical = true;
}
else if (ffStrEquals(desc, "discharge rate"))
}
} else if (ffStrEquals(desc, "discharge rate")) {
prop_dictionary_get_uint(dict, "cur-value", &dischargeRate);
}
}
if (max > 0)
{
if (max > 0) {
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
@@ -87,17 +86,18 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
battery->timeRemaining = -1;
battery->capacity = (double) curr / (double) max * 100.;
if (charging)
if (charging) {
ffStrbufAppendS(&battery->status, "Charging, ");
else if (dischargeRate)
{
} else if (dischargeRate) {
ffStrbufAppendS(&battery->status, "Discharging, ");
battery->timeRemaining = (int32_t)((double)curr / dischargeRate * 3600);
battery->timeRemaining = (int32_t) ((double) curr / dischargeRate * 3600);
}
if (critical)
if (critical) {
ffStrbufAppendS(&battery->status, "Critical, ");
if (acConnected)
}
if (acConnected) {
ffStrbufAppendS(&battery->status, "AC Connected");
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
+1 -2
View File
@@ -1,8 +1,7 @@
#include "fastfetch.h"
#include "battery.h"
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
FF_UNUSED(options, results)
return "Not supported on this platform";
}
+15 -12
View File
@@ -6,19 +6,22 @@
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* result)
{
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* result) {
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY | O_CLOEXEC);
if (devfd < 0) return "open(dev/apm, O_RDONLY | O_CLOEXEC) failed";
if (devfd < 0) {
return "open(dev/apm, O_RDONLY | O_CLOEXEC) failed";
}
struct apm_power_info info = {};
if (ioctl(devfd, APM_IOC_GETPOWER, &info) < 0)
if (ioctl(devfd, APM_IOC_GETPOWER, &info) < 0) {
return "ioctl(APM_IOC_GETPOWER) failed";
}
if (info.battery_state == APM_BATTERY_ABSENT)
if (info.battery_state == APM_BATTERY_ABSENT) {
return NULL;
}
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(result);
battery->temperature = FF_BATTERY_TEMP_UNSET;
@@ -32,19 +35,19 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
if (info.ac_state == APM_AC_ON)
if (info.ac_state == APM_AC_ON) {
ffStrbufAppendS(&battery->status, "AC Connected");
else if (info.ac_state == APM_AC_BACKUP)
} else if (info.ac_state == APM_AC_BACKUP) {
ffStrbufAppendS(&battery->status, "Backup In Use");
else if (info.ac_state == APM_AC_OFF)
{
} else if (info.ac_state == APM_AC_OFF) {
battery->timeRemaining = (int) info.minutes_left * 60;
ffStrbufAppendS(&battery->status, "Discharging");
}
if (info.battery_state == APM_BATT_CRITICAL || info.battery_state == APM_BATT_CHARGING)
{
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
if (info.battery_state == APM_BATT_CRITICAL || info.battery_state == APM_BATT_CHARGING) {
if (battery->status.length) {
ffStrbufAppendS(&battery->status, ", ");
}
ffStrbufAppendS(&battery->status, info.battery_state == APM_BATT_CRITICAL ? "Critical" : "Charging");
}
+112 -91
View File
@@ -12,129 +12,145 @@
#include <devguid.h>
#include <cfgmgr32.h>
static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results)
{
//https://learn.microsoft.com/en-us/windows-hardware/drivers/install/using-device-interfaces
static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results) {
// https://learn.microsoft.com/en-us/windows-hardware/drivers/install/using-device-interfaces
ULONG cchDeviceInterfaces = 0;
CONFIGRET cr = CM_Get_Device_Interface_List_SizeW(&cchDeviceInterfaces, (LPGUID)&GUID_DEVCLASS_BATTERY, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS)
CONFIGRET cr = CM_Get_Device_Interface_List_SizeW(&cchDeviceInterfaces, (LPGUID) &GUID_DEVCLASS_BATTERY, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS) {
return "CM_Get_Device_Interface_List_SizeW() failed";
}
if (cchDeviceInterfaces <= 1)
if (cchDeviceInterfaces <= 1) {
return NULL; // Not found
}
wchar_t* FF_AUTO_FREE mszDeviceInterfaces = (wchar_t*)malloc(cchDeviceInterfaces * sizeof(wchar_t));
cr = CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVCLASS_BATTERY, NULL, mszDeviceInterfaces, cchDeviceInterfaces, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS)
wchar_t* FF_AUTO_FREE mszDeviceInterfaces = (wchar_t*) malloc(cchDeviceInterfaces * sizeof(wchar_t));
cr = CM_Get_Device_Interface_ListW((LPGUID) &GUID_DEVCLASS_BATTERY, NULL, mszDeviceInterfaces, cchDeviceInterfaces, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS) {
return "CM_Get_Device_Interface_ListW() failed";
}
for (const wchar_t* pDeviceInterface = mszDeviceInterfaces; *pDeviceInterface; pDeviceInterface += wcslen(pDeviceInterface) + 1)
{
for (const wchar_t* pDeviceInterface = mszDeviceInterfaces; *pDeviceInterface; pDeviceInterface += wcslen(pDeviceInterface) + 1) {
HANDLE FF_AUTO_CLOSE_FD hBattery =
CreateFileW(pDeviceInterface, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hBattery == INVALID_HANDLE_VALUE)
if (hBattery == INVALID_HANDLE_VALUE) {
continue;
}
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
BATTERY_QUERY_INFORMATION bqi = {.InformationLevel = BatteryInformation};
DWORD dwWait = 0;
DWORD dwOut;
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
if (!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag) {
continue;
}
BATTERY_INFORMATION bi = {0};
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
if (!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL)) {
continue;
}
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
if (!(bi.Capabilities & BATTERY_SYSTEM_BATTERY)) {
continue;
}
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
if (memcmp(bi.Chemistry, "PbAc", 4) == 0) {
ffStrbufInitStatic(&battery->technology, "Lead Acid");
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
} else if (memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0) {
ffStrbufInitStatic(&battery->technology, "Lithium Ion");
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
} else if (memcmp(bi.Chemistry, "NiCd", 4) == 0) {
ffStrbufInitStatic(&battery->technology, "Nickel Cadmium");
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
} else if (memcmp(bi.Chemistry, "NiMH", 4) == 0) {
ffStrbufInitStatic(&battery->technology, "Nickel Metal Hydride");
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
} else if (memcmp(bi.Chemistry, "NiZn", 4) == 0) {
ffStrbufInitStatic(&battery->technology, "Nickel Zinc");
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
} else if (memcmp(bi.Chemistry, "RAM\0", 4) == 0) {
ffStrbufInitStatic(&battery->technology, "Rechargeable Alkaline-Manganese");
else
} else {
ffStrbufInitStatic(&battery->technology, "Unknown");
}
{
ffStrbufInit(&battery->modelName);
bqi.InformationLevel = BatteryDeviceName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL)) {
ffStrbufSetWS(&battery->modelName, name);
}
}
{
ffStrbufInit(&battery->manufacturer);
bqi.InformationLevel = BatteryManufactureName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL)) {
ffStrbufSetWS(&battery->manufacturer, name);
}
}
{
ffStrbufInit(&battery->manufactureDate);
bqi.InformationLevel = BatteryManufactureDate;
BATTERY_MANUFACTURE_DATE date;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL))
if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL)) {
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year < 1000 ? date.Year + 1900 : date.Year, date.Month, date.Day);
}
}
{
ffStrbufInit(&battery->serial);
bqi.InformationLevel = BatterySerialNumber;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL)) {
ffStrbufSetWS(&battery->serial, name);
}
}
battery->cycleCount = bi.CycleCount;
battery->temperature = FF_BATTERY_TEMP_UNSET;
if(options->temp)
{
if (options->temp) {
bqi.InformationLevel = BatteryTemperature;
ULONG temp;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL)) {
battery->temperature = temp / 10.0 - 273.15;
}
}
{
bqi.InformationLevel = BatteryEstimatedTime;
ULONG time;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &time, sizeof(time), &dwOut, NULL))
if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &time, sizeof(time), &dwOut, NULL)) {
battery->timeRemaining = time == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) time;
}
}
{
BATTERY_STATUS bs;
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY && bi.FullChargedCapacity != 0)
BATTERY_WAIT_STATUS bws = {.BatteryTag = bqi.BatteryTag};
if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY && bi.FullChargedCapacity != 0) {
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
else
} else {
battery->capacity = 0;
}
ffStrbufInit(&battery->status);
if(bs.PowerState & BATTERY_POWER_ON_LINE)
if (bs.PowerState & BATTERY_POWER_ON_LINE) {
ffStrbufAppendS(&battery->status, "AC Connected, ");
if(bs.PowerState & BATTERY_DISCHARGING)
}
if (bs.PowerState & BATTERY_DISCHARGING) {
ffStrbufAppendS(&battery->status, "Discharging, ");
if(bs.PowerState & BATTERY_CHARGING)
}
if (bs.PowerState & BATTERY_CHARGING) {
ffStrbufAppendS(&battery->status, "Charging, ");
if(bs.PowerState & BATTERY_CRITICAL)
}
if (bs.PowerState & BATTERY_CRITICAL) {
ffStrbufAppendS(&battery->status, "Critical, ");
}
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
@@ -142,42 +158,42 @@ static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results)
return NULL;
}
typedef struct FFSmbiosPortableBattery
{
typedef struct FFSmbiosPortableBattery {
FFSmbiosHeader Header;
// 2.1+
uint8_t Location; // string
uint8_t Manufacturer; // string
uint8_t ManufactureDate; // string
uint8_t SerialNumber; // string
uint8_t DeviceName; // string
uint8_t DeviceChemistry; // enum
uint16_t DesignCapacity; // varies
uint16_t DesignVoltage; // varies
uint8_t SbdsVersionNumber; // string
uint8_t Location; // string
uint8_t Manufacturer; // string
uint8_t ManufactureDate; // string
uint8_t SerialNumber; // string
uint8_t DeviceName; // string
uint8_t DeviceChemistry; // enum
uint16_t DesignCapacity; // varies
uint16_t DesignVoltage; // varies
uint8_t SbdsVersionNumber; // string
uint8_t MaximumErrorInBatteryData; // varies
// 2.2+
uint16_t SbdsSerialNumber; // varies
uint16_t SbdsManufactureDate; // varies
uint8_t SbdsDeviceChemistry; // string
uint16_t SbdsSerialNumber; // varies
uint16_t SbdsManufactureDate; // varies
uint8_t SbdsDeviceChemistry; // string
uint8_t DesignCapacityMultiplier; // varies
uint16_t OEMSpecific; // varies
uint16_t OEMSpecific; // varies
} __attribute__((__packed__)) FFSmbiosPortableBattery;
static_assert(offsetof(FFSmbiosPortableBattery, OEMSpecific) == 0x16,
"FFSmbiosPortableBattery: Wrong struct alignment");
static const char* detectBySmbios(FFBatteryResult* battery)
{
static const char* detectBySmbios(FFBatteryResult* battery) {
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
if (!smbiosTable)
if (!smbiosTable) {
return "Failed to get SMBIOS data";
}
const FFSmbiosPortableBattery* data = (const FFSmbiosPortableBattery*) (*smbiosTable)[FF_SMBIOS_TYPE_PORTABLE_BATTERY];
if (!data)
if (!data) {
return "Portable battery section is not found in SMBIOS data";
}
const char* strings = (const char*) data + data->Header.Length;
@@ -186,50 +202,57 @@ static const char* detectBySmbios(FFBatteryResult* battery)
ffStrbufSetStatic(&battery->manufacturer, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&battery->manufacturer);
if (data->ManufactureDate)
{
if (data->ManufactureDate) {
ffStrbufSetStatic(&battery->manufactureDate, ffSmbiosLocateString(strings, data->ManufactureDate));
ffCleanUpSmbiosValue(&battery->manufactureDate);
}
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsManufactureDate))
{
} else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsManufactureDate)) {
int day = data->SbdsManufactureDate & 0b11111;
int month = (data->SbdsManufactureDate >> 5) & 0b1111;
int year = (data->SbdsManufactureDate >> 9) + 1800;
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
switch (data->DeviceChemistry)
{
case 0x01: ffStrbufSetStatic(&battery->technology, "Other"); break;
case 0x02: ffStrbufSetStatic(&battery->technology, "Unknown"); break;
case 0x03: ffStrbufSetStatic(&battery->technology, "Lead Acid"); break;
case 0x04: ffStrbufSetStatic(&battery->technology, "Nickel Cadmium"); break;
case 0x05: ffStrbufSetStatic(&battery->technology, "Nickel metal hydride"); break;
case 0x06: ffStrbufSetStatic(&battery->technology, "Lithium-ion"); break;
case 0x07: ffStrbufSetStatic(&battery->technology, "Zinc air"); break;
case 0x08: ffStrbufSetStatic(&battery->technology, "Lithium Polymer"); break;
switch (data->DeviceChemistry) {
case 0x01:
ffStrbufSetStatic(&battery->technology, "Other");
break;
case 0x02:
ffStrbufSetStatic(&battery->technology, "Unknown");
break;
case 0x03:
ffStrbufSetStatic(&battery->technology, "Lead Acid");
break;
case 0x04:
ffStrbufSetStatic(&battery->technology, "Nickel Cadmium");
break;
case 0x05:
ffStrbufSetStatic(&battery->technology, "Nickel metal hydride");
break;
case 0x06:
ffStrbufSetStatic(&battery->technology, "Lithium-ion");
break;
case 0x07:
ffStrbufSetStatic(&battery->technology, "Zinc air");
break;
case 0x08:
ffStrbufSetStatic(&battery->technology, "Lithium Polymer");
break;
}
if (data->SerialNumber)
{
if (data->SerialNumber) {
ffStrbufSetStatic(&battery->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&battery->serial);
}
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsSerialNumber))
{
} else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsSerialNumber)) {
ffStrbufSetF(&battery->serial, "%4X", data->SbdsSerialNumber);
}
return NULL;
}
static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results) {
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
{
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent) {
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->manufactureDate);
@@ -241,15 +264,14 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
battery->timeRemaining = info.EstimatedTime == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) info.EstimatedTime;
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
if(info.AcOnLine)
{
if (info.AcOnLine) {
ffStrbufAppendS(&battery->status, "AC Connected");
if(info.Charging)
if (info.Charging) {
ffStrbufAppendS(&battery->status, ", Charging");
}
else if(info.Discharging)
}
} else if (info.Discharging) {
ffStrbufAppendS(&battery->status, "Discharging");
}
detectBySmbios(battery);
@@ -258,8 +280,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
return "NtPowerInformation(SystemBatteryState) failed";
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) {
return options->useSetupApi
? detectWithCmApi(options, results)
: detectWithNtApi(options, results);
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/bios/option.h"
typedef struct FFBiosResult
{
typedef struct FFBiosResult {
FFstrbuf date;
FFstrbuf release;
FFstrbuf vendor;
+5 -4
View File
@@ -1,13 +1,14 @@
#include "bios.h"
#include "common/settings.h"
const char* ffDetectBios(FFBiosResult* bios)
{
if (!ffSettingsGetAndroidProperty("ro.bootloader", &bios->version))
const char* ffDetectBios(FFBiosResult* bios) {
if (!ffSettingsGetAndroidProperty("ro.bootloader", &bios->version)) {
ffSettingsGetAndroidProperty("ro.boot.bootloader", &bios->version);
}
if (ffStrbufIgnCaseEqualS(&bios->version, "unknown"))
if (ffStrbufIgnCaseEqualS(&bios->version, "unknown")) {
ffStrbufClear(&bios->version);
}
ffStrbufSetStatic(&bios->type, "Bootloader");
+18 -18
View File
@@ -3,31 +3,33 @@
#include <IOKit/IOKitLib.h>
const char* ffDetectBios(FFBiosResult* bios)
{
#ifndef __aarch64__
const char* ffDetectBios(FFBiosResult* bios) {
#ifndef __aarch64__
//https://github.com/osquery/osquery/blob/master/osquery/tables/system/darwin/smbios_tables.cpp
//For Intel
// https://github.com/osquery/osquery/blob/master/osquery/tables/system/darwin/smbios_tables.cpp
// For Intel
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceRom = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom");
if (!deviceRom)
if (!deviceRom) {
return "IODeviceTree:/rom not found";
}
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef deviceRomProps = NULL;
if(IORegistryEntryCreateCFProperties(deviceRom, &deviceRomProps, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
if (IORegistryEntryCreateCFProperties(deviceRom, &deviceRomProps, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) {
return "IORegistryEntryCreateCFProperties(deviceRom) failed";
}
ffCfDictGetString(deviceRomProps, CFSTR("vendor"), &bios->vendor);
ffCfDictGetString(deviceRomProps, CFSTR("version"), &bios->version);
ffCfDictGetString(deviceRomProps, CFSTR("release-date"), &bios->date);
ffStrbufSetStatic(&bios->type, "UEFI");
#else
#else
//For arm64
// For arm64
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t device = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/");
if (!device)
if (!device) {
return "IODeviceTree:/ not found";
}
FF_CFTYPE_AUTO_RELEASE CFDataRef manufacturer = IORegistryEntryCreateCFProperty(device, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
ffCfStrGetString(manufacturer, &bios->vendor);
@@ -35,23 +37,21 @@ const char* ffDetectBios(FFBiosResult* bios)
ffCfStrGetString(timeStamp, &bios->date);
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceChosen = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen");
if (deviceChosen)
{
if (deviceChosen) {
FF_CFTYPE_AUTO_RELEASE CFStringRef systemFirmwareVersion = IORegistryEntryCreateCFProperty(deviceChosen, CFSTR("system-firmware-version"), kCFAllocatorDefault, kNilOptions);
if (systemFirmwareVersion)
{
if (systemFirmwareVersion) {
ffCfStrGetString(systemFirmwareVersion, &bios->version);
uint32_t index = ffStrbufFirstIndexC(&bios->version, '-');
if (index != bios->version.length)
{
if (index != bios->version.length) {
ffStrbufAppendNS(&bios->type, index, bios->version.chars);
ffStrbufRemoveSubstr(&bios->version, 0, index + 1);
}
}
}
if (!bios->type.length)
if (!bios->type.length) {
ffStrbufSetStatic(&bios->type, "iBoot");
#endif
}
#endif
return NULL;
}
+7 -9
View File
@@ -5,8 +5,7 @@
#include "common/io.h"
#include "common/smbiosHelper.h"
const char* ffDetectBios(FFBiosResult* result)
{
const char* ffDetectBios(FFBiosResult* result) {
ffSettingsGetFreeBSDKenv("smbios.bios.reldate", &result->date);
ffCleanUpSmbiosValue(&result->date);
ffSettingsGetFreeBSDKenv("smbios.bios.revision", &result->release);
@@ -17,16 +16,15 @@ const char* ffDetectBios(FFBiosResult* result)
ffCleanUpSmbiosValue(&result->version);
ffSysctlGetString("machdep.bootmethod", &result->type);
if (result->type.length == 0)
{
if (ffSettingsGetFreeBSDKenv("loader.efi", &result->type))
if (result->type.length == 0) {
if (ffSettingsGetFreeBSDKenv("loader.efi", &result->type)) {
ffStrbufSetStatic(&result->type, ffStrbufEqualS(&result->type, "1") ? "UEFI" : "BIOS");
else
{
} else {
ffStrbufSetStatic(&result->type,
ffPathExists("/dev/efi" /*efidev*/, FF_PATHTYPE_FILE) ||
ffPathExists("/boot/efi/efi/" /*efi partition. Note /boot/efi exists on BIOS system*/, FF_PATHTYPE_DIRECTORY)
? "UEFI" : "BIOS");
ffPathExists("/boot/efi/efi/" /*efi partition. Note /boot/efi exists on BIOS system*/, FF_PATHTYPE_DIRECTORY)
? "UEFI"
: "BIOS");
}
}
return NULL;
+6 -9
View File
@@ -2,23 +2,20 @@
#include "common/io.h"
#include "common/smbiosHelper.h"
const char* ffDetectBios(FFBiosResult* bios)
{
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date))
{
const char* ffDetectBios(FFBiosResult* bios) {
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date)) {
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version);
}
else if (ffReadFileBuffer("/proc/device-tree/chosen/u-boot,version", &bios->version))
{
} else if (ffReadFileBuffer("/proc/device-tree/chosen/u-boot,version", &bios->version)) {
ffStrbufTrimRight(&bios->version, '\0');
ffStrbufSetStatic(&bios->vendor, "U-Boot");
}
if (ffPathExists("/sys/firmware/efi/", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE))
if (ffPathExists("/sys/firmware/efi/", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE)) {
ffStrbufSetStatic(&bios->type, "UEFI");
else
} else {
ffStrbufSetStatic(&bios->type, "BIOS");
}
return NULL;
}
+7 -5
View File
@@ -2,14 +2,16 @@
#include "common/sysctl.h"
#include "common/smbiosHelper.h"
const char* ffDetectBios(FFBiosResult* bios)
{
if (ffSysctlGetString("machdep.dmi.bios-date", &bios->date) == NULL)
const char* ffDetectBios(FFBiosResult* bios) {
if (ffSysctlGetString("machdep.dmi.bios-date", &bios->date) == NULL) {
ffCleanUpSmbiosValue(&bios->date);
if (ffSysctlGetString("machdep.dmi.bios-version", &bios->version) == NULL)
}
if (ffSysctlGetString("machdep.dmi.bios-version", &bios->version) == NULL) {
ffCleanUpSmbiosValue(&bios->version);
if (ffSysctlGetString("machdep.dmi.bios-vendor", &bios->vendor) == NULL)
}
if (ffSysctlGetString("machdep.dmi.bios-vendor", &bios->vendor) == NULL) {
ffCleanUpSmbiosValue(&bios->vendor);
}
ffSysctlGetString("machdep.bootmethod", &bios->type);
return NULL;
}
+1 -2
View File
@@ -1,6 +1,5 @@
#include "bios.h"
const char* ffDetectBios(FF_MAYBE_UNUSED FFBiosResult* bios)
{
const char* ffDetectBios(FF_MAYBE_UNUSED FFBiosResult* bios) {
return "Not supported on this platform";
}
+45 -42
View File
@@ -2,38 +2,37 @@
#include "common/smbiosHelper.h"
#ifdef _WIN32
#include "common/windows/registry.h"
# include "common/windows/registry.h"
#include <ntstatus.h>
#include "common/windows/nt.h"
# include <ntstatus.h>
# include "common/windows/nt.h"
#elif __OpenBSD__
#include "common/io.h"
# include "common/io.h"
#include <fcntl.h>
#include <unistd.h>
# include <fcntl.h>
# include <unistd.h>
#elif __sun
#include <libdevinfo.h>
#include <sys/sunddi.h>
# include <libdevinfo.h>
# include <sys/sunddi.h>
#elif __APPLE__
#include "common/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
# include "common/apple/cf_helpers.h"
# include <IOKit/IOKitLib.h>
#endif
typedef struct FFSmbiosBios
{
typedef struct FFSmbiosBios {
FFSmbiosHeader Header;
uint8_t Vendor; // string
uint8_t BiosVersion; // string
uint8_t Vendor; // string
uint8_t BiosVersion; // string
uint16_t BiosStartingAddressSegment; // varies
uint8_t BiosReleaseDate; // string
uint8_t BiosRomSize; // string
uint64_t BiosCharacteristics; // bit field
uint8_t BiosReleaseDate; // string
uint8_t BiosRomSize; // string
uint64_t BiosCharacteristics; // bit field
// 2.4+
uint8_t BiosCharacteristicsExtensionBytes[2]; // bit field
uint8_t SystemBiosMajorRelease; // varies
uint8_t SystemBiosMinorRelease; // varies
uint8_t BiosCharacteristicsExtensionBytes[2]; // bit field
uint8_t SystemBiosMajorRelease; // varies
uint8_t SystemBiosMinorRelease; // varies
uint8_t EmbeddedControllerFirmwareMajorRelease; // varies
uint8_t EmbeddedControllerFirmwareMinorRelease; // varies
@@ -44,16 +43,16 @@ typedef struct FFSmbiosBios
static_assert(offsetof(FFSmbiosBios, ExtendedBiosRomSize) == 0x18,
"FFSmbiosBios: Wrong struct alignment");
const char* ffDetectBios(FFBiosResult* bios)
{
const char* ffDetectBios(FFBiosResult* bios) {
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
if (!smbiosTable)
if (!smbiosTable) {
return "Failed to get SMBIOS data";
}
const FFSmbiosBios* data = (const FFSmbiosBios*) (*smbiosTable)[FF_SMBIOS_TYPE_BIOS];
if (!data)
if (!data) {
return "BIOS section is not found in SMBIOS data";
}
const char* strings = (const char*) data + data->Header.Length;
@@ -64,41 +63,45 @@ const char* ffDetectBios(FFBiosResult* bios)
ffStrbufSetStatic(&bios->date, ffSmbiosLocateString(strings, data->BiosReleaseDate));
ffCleanUpSmbiosValue(&bios->date);
if (data->Header.Length > offsetof(FFSmbiosBios, SystemBiosMajorRelease))
if (data->Header.Length > offsetof(FFSmbiosBios, SystemBiosMajorRelease)) {
ffStrbufSetF(&bios->release, "%u.%u", data->SystemBiosMajorRelease, data->SystemBiosMinorRelease);
}
#ifdef _WIN32
#ifdef _WIN32
// Same as GetFirmwareType, but support (?) Windows 7
// https://ntdoc.m417z.com/system_information_class
SYSTEM_BOOT_ENVIRONMENT_INFORMATION sbei;
if (NT_SUCCESS(NtQuerySystemInformation(SystemBootEnvironmentInformation, &sbei, sizeof(sbei), NULL)))
{
switch (sbei.FirmwareType)
{
case FirmwareTypeBios: ffStrbufSetStatic(&bios->type, "BIOS"); break;
case FirmwareTypeUefi: ffStrbufSetStatic(&bios->type, "UEFI"); break;
default: break;
if (NT_SUCCESS(NtQuerySystemInformation(SystemBootEnvironmentInformation, &sbei, sizeof(sbei), NULL))) {
switch (sbei.FirmwareType) {
case FirmwareTypeBios:
ffStrbufSetStatic(&bios->type, "BIOS");
break;
case FirmwareTypeUefi:
ffStrbufSetStatic(&bios->type, "UEFI");
break;
default:
break;
}
}
#elif __sun
#elif __sun
di_node_t rootNode = di_init("/", DINFOPROP);
if (rootNode != DI_NODE_NIL)
{
if (rootNode != DI_NODE_NIL) {
char* efiVersion = NULL;
if (di_prop_lookup_strings(DDI_DEV_T_ANY, rootNode, "efi-version", &efiVersion) > 0)
if (di_prop_lookup_strings(DDI_DEV_T_ANY, rootNode, "efi-version", &efiVersion) > 0) {
ffStrbufSetStatic(&bios->type, "UEFI");
else
} else {
ffStrbufSetStatic(&bios->type, "BIOS");
}
}
di_fini(rootNode);
#elif __HAIKU__ || __OpenBSD__
#elif __HAIKU__ || __OpenBSD__
// Currently SMBIOS detection is supported in legacy BIOS only
ffStrbufSetStatic(&bios->type, "BIOS");
#elif __APPLE__
#elif __APPLE__
// Intel Macs use UEFI from day one
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceEfi = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/efi");
ffStrbufSetStatic(&bios->type, deviceEfi ? "UEFI" : "BIOS");
#endif
#endif
return NULL;
}
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/bluetooth/option.h"
typedef struct FFBluetoothResult
{
typedef struct FFBluetoothResult {
FFstrbuf name;
FFstrbuf address;
FFstrbuf type;
+7 -8
View File
@@ -3,15 +3,14 @@
#define L2CAP_SOCKET_CHECKED
#include <bluetooth.h>
static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFlist* devices)
{
static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFlist* devices) {
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name,
#if __FreeBSD__
#if __FreeBSD__
bt_devremote_name_gen(dev->devname, &dev->bdaddr)
#else
#else
dev->devname
#endif
#endif
);
ffStrbufInitS(&device->address, bt_ntoa(&dev->bdaddr, NULL));
ffStrbufUpperCase(&device->address);
@@ -21,11 +20,11 @@ static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFl
return 0;
}
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */) {
// struct hostent* ent = bt_gethostent();
if (bt_devenum((void*) enumDev, devices) < 0)
if (bt_devenum((void*) enumDev, devices) < 0) {
return "bt_devenum() failed";
}
return NULL;
}
+4 -3
View File
@@ -5,13 +5,14 @@ extern "C" {
#include <bluetooth/LocalDevice.h>
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
{
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */) {
using namespace Bluetooth;
FF_SUPPRESS_IO();
LocalDevice* dev = LocalDevice::GetLocalDevice();
if (!dev) return NULL;
if (!dev) {
return NULL;
}
BString devClass;
dev->GetDeviceClass().DumpDeviceClass(devClass);
+71 -70
View File
@@ -2,8 +2,8 @@
#include "common/stringUtils.h"
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/io.h"
# include "common/dbus.h"
# include "common/io.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
@@ -45,103 +45,108 @@ array [ //root
]
*/
static bool detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
static bool detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device) {
if (dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) {
return true;
}
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
if (dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) {
return true;
}
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(ffStrEquals(deviceProperty, "Address"))
if (ffStrEquals(deviceProperty, "Address")) {
ffDBusGetString(dbus, &dictIter, &device->address);
else if(ffStrEquals(deviceProperty, "Name"))
} else if (ffStrEquals(deviceProperty, "Name")) {
ffDBusGetString(dbus, &dictIter, &device->name);
else if(ffStrEquals(deviceProperty, "Icon"))
} else if (ffStrEquals(deviceProperty, "Icon")) {
ffDBusGetString(dbus, &dictIter, &device->type);
else if(ffStrEquals(deviceProperty, "Percentage"))
{
} else if (ffStrEquals(deviceProperty, "Percentage")) {
uint32_t percentage;
if (ffDBusGetUint(dbus, &dictIter, &percentage))
if (ffDBusGetUint(dbus, &dictIter, &percentage)) {
device->battery = (uint8_t) percentage;
}
else if(ffStrEquals(deviceProperty, "Connected"))
}
} else if (ffStrEquals(deviceProperty, "Connected")) {
ffDBusGetBool(dbus, &dictIter, &device->connected);
else if(ffStrEquals(deviceProperty, "Paired"))
{
} else if (ffStrEquals(deviceProperty, "Paired")) {
bool paired = true;
ffDBusGetBool(dbus, &dictIter, &paired);
if (!paired) return false;
if (!paired) {
return false;
}
}
return true;
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device) {
if (dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) {
return;
}
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
if (dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) {
return;
}
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(!ffStrContains(propertyType, ".Device") && !ffStrContains(propertyType, ".Battery"))
if (!ffStrContains(propertyType, ".Device") && !ffStrContains(propertyType, ".Battery")) {
return; // We don't care about other properties
}
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
if (dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY) {
return;
}
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
do
{
do {
bool shouldContinue = detectBluetoothValue(dbus, &arrayIter, device);
if (!shouldContinue)
{
if (!shouldContinue) {
ffStrbufClear(&device->name);
break;
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static FFBluetoothResult* detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
static FFBluetoothResult* detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter) {
if (dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) {
return NULL;
}
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
if (dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH) {
return NULL;
}
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
// We don't want adapter objects
if(!ffStrContains(objectPath, "/dev_"))
if (!ffStrContains(objectPath, "/dev_")) {
return NULL;
}
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
if (dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY) {
return NULL;
}
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
@@ -153,56 +158,53 @@ static FFBluetoothResult* detectBluetoothObject(FFlist* devices, FFDBusData* dbu
device->battery = 0;
device->connected = false;
do
{
do {
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
return device;
}
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter, int32_t connectedCount)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter, int32_t connectedCount) {
if (dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
return;
}
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
do
{
do {
FFBluetoothResult* device = detectBluetoothObject(devices, dbus, &arrayIter);
if (device)
{
if(device->name.length == 0 || (connectedCount > 0 && !device->connected))
{
if (device) {
if (device->name.length == 0 || (connectedCount > 0 && !device->connected)) {
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--devices->length;
}
if (device->connected && --connectedCount == 0)
if (device->connected && --connectedCount == 0) {
break;
}
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static const char* detectBluetooth(FFlist* devices, int32_t connectedCount)
{
static const char* detectBluetooth(FFlist* devices, int32_t connectedCount) {
FF_DBUS_AUTO_DESTROY_DATA FFDBusData dbus = {};
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
if (error) {
return error;
}
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL, NULL);
if(!managedObjects)
if (!managedObjects) {
return "Failed to call GetManagedObjects";
}
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
{
if (!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter)) {
dbus.lib->ffdbus_message_unref(managedObjects);
return "Failed to get root iterator of GetManagedObjects";
}
@@ -213,18 +215,18 @@ static const char* detectBluetooth(FFlist* devices, int32_t connectedCount)
return NULL;
}
static uint32_t connectedDevices(void)
{
static uint32_t connectedDevices(void) {
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
if(dirp == NULL)
if (dirp == NULL) {
return 0;
}
uint32_t result = 0;
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (strchr(entry->d_name, ':') != NULL)
while ((entry = readdir(dirp)) != NULL) {
if (strchr(entry->d_name, ':') != NULL) {
++result;
}
}
return result;
@@ -232,19 +234,18 @@ static uint32_t connectedDevices(void)
#endif
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
#ifdef FF_HAVE_DBUS
int32_t connectedCount = -1;
if (!options->showDisconnected)
{
connectedCount = (int32_t) connectedDevices();
if (connectedCount == 0)
return NULL;
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */) {
#ifdef FF_HAVE_DBUS
int32_t connectedCount = -1;
if (!options->showDisconnected) {
connectedCount = (int32_t) connectedDevices();
if (connectedCount == 0) {
return NULL;
}
}
return detectBluetooth(devices, connectedCount);
#else
return "Fastfetch was compiled without DBus support";
#endif
return detectBluetooth(devices, connectedCount);
#else
return "Fastfetch was compiled without DBus support";
#endif
}
@@ -1,6 +1,5 @@
#include "bluetooth.h"
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */) {
return "Not supported on this platform";
}
+38 -39
View File
@@ -7,73 +7,74 @@
#pragma GCC diagnostic ignored "-Wpointer-sign"
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
{
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */) {
FF_LIBRARY_LOAD_MESSAGE(bluetoothapis, "bluetoothapis.dll", 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstDevice)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextDevice)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindDeviceClose)
BLUETOOTH_DEVICE_INFO btdi = {
.dwSize = sizeof(btdi)
};
.dwSize = sizeof(btdi)};
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&(BLUETOOTH_DEVICE_SEARCH_PARAMS) {
.fReturnConnected = TRUE,
.fReturnRemembered = options->showDisconnected,
.fReturnAuthenticated = options->showDisconnected,
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS)
}, &btdi);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
.fReturnConnected = TRUE,
.fReturnRemembered = options->showDisconnected,
.fReturnAuthenticated = options->showDisconnected,
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS)},
&btdi);
if (!hFind) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
return NULL;
}
return "BluetoothFindFirstDevice() failed";
}
do {
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitWS(&device->name, btdi.szName);
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X",
btdi.Address.rgBytes[5],
btdi.Address.rgBytes[4],
btdi.Address.rgBytes[3],
btdi.Address.rgBytes[2],
btdi.Address.rgBytes[1],
btdi.Address.rgBytes[0]);
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X", btdi.Address.rgBytes[5], btdi.Address.rgBytes[4], btdi.Address.rgBytes[3], btdi.Address.rgBytes[2], btdi.Address.rgBytes[1], btdi.Address.rgBytes[0]);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!btdi.fConnected;
//https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
// https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
if(BitTest(&btdi.ulClassofDevice, 13))
if (BitTest(&btdi.ulClassofDevice, 13)) {
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
if(BitTest(&btdi.ulClassofDevice, 14))
}
if (BitTest(&btdi.ulClassofDevice, 14)) {
ffStrbufAppendS(&device->type, "LE audio, ");
if(BitTest(&btdi.ulClassofDevice, 15))
}
if (BitTest(&btdi.ulClassofDevice, 15)) {
ffStrbufAppendS(&device->type, "Reserved for future use, ");
if(BitTest(&btdi.ulClassofDevice, 16))
}
if (BitTest(&btdi.ulClassofDevice, 16)) {
ffStrbufAppendS(&device->type, "Positioning, ");
if(BitTest(&btdi.ulClassofDevice, 17))
}
if (BitTest(&btdi.ulClassofDevice, 17)) {
ffStrbufAppendS(&device->type, "Networking, ");
if(BitTest(&btdi.ulClassofDevice, 18))
}
if (BitTest(&btdi.ulClassofDevice, 18)) {
ffStrbufAppendS(&device->type, "Rendering, ");
if(BitTest(&btdi.ulClassofDevice, 19))
}
if (BitTest(&btdi.ulClassofDevice, 19)) {
ffStrbufAppendS(&device->type, "Capturing, ");
if(BitTest(&btdi.ulClassofDevice, 20))
}
if (BitTest(&btdi.ulClassofDevice, 20)) {
ffStrbufAppendS(&device->type, "Object Transfer, ");
if(BitTest(&btdi.ulClassofDevice, 21))
}
if (BitTest(&btdi.ulClassofDevice, 21)) {
ffStrbufAppendS(&device->type, "Audio, ");
if(BitTest(&btdi.ulClassofDevice, 22))
}
if (BitTest(&btdi.ulClassofDevice, 22)) {
ffStrbufAppendS(&device->type, "Telephony, ");
if(BitTest(&btdi.ulClassofDevice, 23))
}
if (BitTest(&btdi.ulClassofDevice, 23)) {
ffStrbufAppendS(&device->type, "Information, ");
}
if(device->type.length == 0)
{
if (device->type.length == 0) {
uint32_t majorDeviceClasses = (btdi.ulClassofDevice >> 8) & ~(UINT32_MAX << 5);
switch(majorDeviceClasses)
{
switch (majorDeviceClasses) {
case 0b00000:
ffStrbufAppendS(&device->type, "Miscellaneous");
break;
@@ -111,9 +112,7 @@ const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FF
ffStrbufAppendS(&device->type, "Unknown");
break;
}
}
else
{
} else {
ffStrbufTrimRight(&device->type, ' ');
ffStrbufTrimRight(&device->type, ',');
}
@@ -121,7 +120,7 @@ const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FF
ffBluetoothFindDeviceClose(hFind);
const char* ffBluetoothDetectBattery(FFlist* result);
const char* ffBluetoothDetectBattery(FFlist * result);
ffBluetoothDetectBattery(devices);
return NULL;
+33 -30
View File
@@ -1,84 +1,88 @@
extern "C"
{
extern "C" {
#include "bluetooth.h"
}
#include "common/windows/wmi.hpp"
#include "common/windows/unicode.hpp"
#include "common/windows/util.hpp"
extern "C"
const char* ffBluetoothDetectBattery(FFlist* devices)
{
extern "C" const char* ffBluetoothDetectBattery(FFlist* devices) {
FFWmiQuery query(L"SELECT __PATH FROM Win32_PnPEntity WHERE Service = 'BthHFEnum'", nullptr, FFWmiNamespace::CIMV2);
if(!query)
if (!query) {
return "Query WMI service failed";
}
IWbemClassObject* pInParams = nullptr;
on_scope_exit releaseInParams([&] { pInParams && pInParams->Release(); });
{
IWbemClassObject* pnpEntityClass = nullptr;
if (FAILED(query.pService->GetObjectW(bstr_t(L"Win32_PnPEntity"), 0, nullptr, &pnpEntityClass, nullptr)))
if (FAILED(query.pService->GetObjectW(bstr_t(L"Win32_PnPEntity"), 0, nullptr, &pnpEntityClass, nullptr))) {
return "Failed to get PnP entity class";
}
on_scope_exit releasePnpEntityClass([&] { pnpEntityClass && pnpEntityClass->Release(); });
if (FAILED(pnpEntityClass->GetMethod(bstr_t(L"GetDeviceProperties"), 0, &pInParams, NULL)))
if (FAILED(pnpEntityClass->GetMethod(bstr_t(L"GetDeviceProperties"), 0, &pInParams, NULL))) {
return "Failed to get GetDeviceProperties method";
}
FFWmiVariant devicePropertyKeys({ L"{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2", L"DEVPKEY_Bluetooth_DeviceAddress" });
if (FAILED(pInParams->Put(L"devicePropertyKeys", 0, &devicePropertyKeys, CIM_FLAG_ARRAY | CIM_STRING)))
FFWmiVariant devicePropertyKeys({L"{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2", L"DEVPKEY_Bluetooth_DeviceAddress"});
if (FAILED(pInParams->Put(L"devicePropertyKeys", 0, &devicePropertyKeys, CIM_FLAG_ARRAY | CIM_STRING))) {
return "Failed to put devicePropertyKeys";
}
}
while (FFWmiRecord record = query.next())
{
while (FFWmiRecord record = query.next()) {
IWbemCallResult* pCallResult = nullptr;
if (FAILED(query.pService->ExecMethod(record.get(L"__PATH").bstrVal, bstr_t(L"GetDeviceProperties"), 0, nullptr, pInParams, nullptr, &pCallResult)))
if (FAILED(query.pService->ExecMethod(record.get(L"__PATH").bstrVal, bstr_t(L"GetDeviceProperties"), 0, nullptr, pInParams, nullptr, &pCallResult))) {
continue;
}
on_scope_exit releaseCallResult([&] { pCallResult && pCallResult->Release(); });
IWbemClassObject* pResultObject = nullptr;
if (FAILED(pCallResult->GetResultObject((LONG) WBEM_INFINITE, &pResultObject)))
if (FAILED(pCallResult->GetResultObject((LONG) WBEM_INFINITE, &pResultObject))) {
continue;
}
on_scope_exit releaseResultObject([&] { pResultObject && pResultObject->Release(); });
VARIANT propArray;
if (FAILED(pResultObject->Get(L"deviceProperties", 0, &propArray, nullptr, nullptr)))
if (FAILED(pResultObject->Get(L"deviceProperties", 0, &propArray, nullptr, nullptr))) {
continue;
}
on_scope_exit releasePropArray([&] { VariantClear(&propArray); });
if (propArray.vt != (VT_ARRAY | VT_UNKNOWN) ||
(propArray.parray->fFeatures & FADF_UNKNOWN) == 0 ||
propArray.parray->cDims != 1 ||
propArray.parray->rgsabound[0].cElements != 2
)
propArray.parray->rgsabound[0].cElements != 2) {
continue;
}
uint8_t batt = 0;
for (LONG i = 0; i < 2; i++)
{
for (LONG i = 0; i < 2; i++) {
IWbemClassObject* object = nullptr;
if (FAILED(SafeArrayGetElement(propArray.parray, &i, &object)))
if (FAILED(SafeArrayGetElement(propArray.parray, &i, &object))) {
continue;
}
FFWmiRecord rec(object);
auto data = rec.get(L"Data");
if (data.vt == VT_EMPTY)
if (data.vt == VT_EMPTY) {
break;
}
if (i == 0)
if (i == 0) {
batt = data.get<uint8_t>();
else
{
} else {
FF_STRBUF_AUTO_DESTROY addr = ffStrbufCreateWSV(data.get<std::wstring_view>()); // MAC address without colon
if (__builtin_expect(addr.length != 12, 0))
if (__builtin_expect(addr.length != 12, 0)) {
continue;
}
FF_LIST_FOR_EACH(FFBluetoothResult, bt, *devices)
{
if (bt->address.length != 12 + 5)
FF_LIST_FOR_EACH (FFBluetoothResult, bt, *devices) {
if (bt->address.length != 12 + 5) {
continue;
}
if (addr.chars[0] == bt->address.chars[0] &&
addr.chars[1] == bt->address.chars[1] &&
@@ -91,8 +95,7 @@ const char* ffBluetoothDetectBattery(FFlist* devices)
addr.chars[8] == bt->address.chars[12] &&
addr.chars[9] == bt->address.chars[13] &&
addr.chars[10] == bt->address.chars[15] &&
addr.chars[11] == bt->address.chars[16])
{
addr.chars[11] == bt->address.chars[16]) {
bt->battery = batt;
break;
}
+104 -55
View File
@@ -53,60 +53,109 @@
#define BTH_MFG_ARUBA_NETWORKS 283
#define BTH_MFG_INTERNAL_USE 65535
const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId)
{
switch (manufacturerId)
{
case BTH_MFG_ERICSSON: return "Ericsson";
case BTH_MFG_NOKIA: return "Nokia";
case BTH_MFG_INTEL: return "Intel";
case BTH_MFG_IBM: return "IBM";
case BTH_MFG_TOSHIBA: return "Toshiba";
case BTH_MFG_3COM: return "3Com";
case BTH_MFG_MICROSOFT: return "Microsoft";
case BTH_MFG_LUCENT: return "Lucent";
case BTH_MFG_MOTOROLA: return "Motorola";
case BTH_MFG_INFINEON: return "Infineon";
case BTH_MFG_CSR: return "CSR";
case BTH_MFG_SILICONWAVE: return "Silicon-Wave";
case BTH_MFG_DIGIANSWER: return "Digi-Answer";
case BTH_MFG_TI: return "Ti";
case BTH_MFG_PARTHUS: return "Parthus";
case BTH_MFG_BROADCOM: return "Broadcom";
case BTH_MFG_MITEL: return "Mitel";
case BTH_MFG_WIDCOMM: return "Widcomm";
case BTH_MFG_ZEEVO: return "Zeevo";
case BTH_MFG_ATMEL: return "Atmel";
case BTH_MFG_MITSIBUSHI: return "Mitsubishi";
case BTH_MFG_RTX_TELECOM: return "RTX Telecom";
case BTH_MFG_KC_TECHNOLOGY: return "KC Technology";
case BTH_MFG_NEWLOGIC: return "Newlogic";
case BTH_MFG_TRANSILICA: return "Transilica";
case BTH_MFG_ROHDE_SCHWARZ: return "Rohde-Schwarz";
case BTH_MFG_TTPCOM: return "TTPCom";
case BTH_MFG_SIGNIA: return "Signia";
case BTH_MFG_CONEXANT: return "Conexant";
case BTH_MFG_QUALCOMM: return "Qualcomm";
case BTH_MFG_INVENTEL: return "Inventel";
case BTH_MFG_AVM_BERLIN: return "AVM Berlin";
case BTH_MFG_BANDSPEED: return "Bandspeed";
case BTH_MFG_MANSELLA: return "Mansella";
case BTH_MFG_NEC: return "NEC";
case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO: return "Waveplus";
case BTH_MFG_ALCATEL: return "Alcatel";
case BTH_MFG_PHILIPS_SEMICONDUCTOR: return "Philips Semiconductors";
case BTH_MFG_C_TECHNOLOGIES: return "C Technologies";
case BTH_MFG_OPEN_INTERFACE: return "Open Interface";
case BTH_MFG_RF_MICRO_DEVICES: return "RF Micro Devices";
case BTH_MFG_HITACHI: return "Hitachi";
case BTH_MFG_SYMBOL_TECHNOLOGIES: return "Symbol Technologies";
case BTH_MFG_TENOVIS: return "Tenovis";
case BTH_MFG_MACRONIX_INTERNATIONAL: return "Macronix International";
case BTH_MFG_MARVELL: return "Marvell";
case BTH_MFG_APPLE: return "Apple";
case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA: return "Nordic Semiconductor ASA";
case BTH_MFG_ARUBA_NETWORKS: return "Aruba Networks";
case BTH_MFG_INTERNAL_USE: return "Internal Use";
default: return "Unknown";
const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId) {
switch (manufacturerId) {
case BTH_MFG_ERICSSON:
return "Ericsson";
case BTH_MFG_NOKIA:
return "Nokia";
case BTH_MFG_INTEL:
return "Intel";
case BTH_MFG_IBM:
return "IBM";
case BTH_MFG_TOSHIBA:
return "Toshiba";
case BTH_MFG_3COM:
return "3Com";
case BTH_MFG_MICROSOFT:
return "Microsoft";
case BTH_MFG_LUCENT:
return "Lucent";
case BTH_MFG_MOTOROLA:
return "Motorola";
case BTH_MFG_INFINEON:
return "Infineon";
case BTH_MFG_CSR:
return "CSR";
case BTH_MFG_SILICONWAVE:
return "Silicon-Wave";
case BTH_MFG_DIGIANSWER:
return "Digi-Answer";
case BTH_MFG_TI:
return "Ti";
case BTH_MFG_PARTHUS:
return "Parthus";
case BTH_MFG_BROADCOM:
return "Broadcom";
case BTH_MFG_MITEL:
return "Mitel";
case BTH_MFG_WIDCOMM:
return "Widcomm";
case BTH_MFG_ZEEVO:
return "Zeevo";
case BTH_MFG_ATMEL:
return "Atmel";
case BTH_MFG_MITSIBUSHI:
return "Mitsubishi";
case BTH_MFG_RTX_TELECOM:
return "RTX Telecom";
case BTH_MFG_KC_TECHNOLOGY:
return "KC Technology";
case BTH_MFG_NEWLOGIC:
return "Newlogic";
case BTH_MFG_TRANSILICA:
return "Transilica";
case BTH_MFG_ROHDE_SCHWARZ:
return "Rohde-Schwarz";
case BTH_MFG_TTPCOM:
return "TTPCom";
case BTH_MFG_SIGNIA:
return "Signia";
case BTH_MFG_CONEXANT:
return "Conexant";
case BTH_MFG_QUALCOMM:
return "Qualcomm";
case BTH_MFG_INVENTEL:
return "Inventel";
case BTH_MFG_AVM_BERLIN:
return "AVM Berlin";
case BTH_MFG_BANDSPEED:
return "Bandspeed";
case BTH_MFG_MANSELLA:
return "Mansella";
case BTH_MFG_NEC:
return "NEC";
case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO:
return "Waveplus";
case BTH_MFG_ALCATEL:
return "Alcatel";
case BTH_MFG_PHILIPS_SEMICONDUCTOR:
return "Philips Semiconductors";
case BTH_MFG_C_TECHNOLOGIES:
return "C Technologies";
case BTH_MFG_OPEN_INTERFACE:
return "Open Interface";
case BTH_MFG_RF_MICRO_DEVICES:
return "RF Micro Devices";
case BTH_MFG_HITACHI:
return "Hitachi";
case BTH_MFG_SYMBOL_TECHNOLOGIES:
return "Symbol Technologies";
case BTH_MFG_TENOVIS:
return "Tenovis";
case BTH_MFG_MACRONIX_INTERNATIONAL:
return "Macronix International";
case BTH_MFG_MARVELL:
return "Marvell";
case BTH_MFG_APPLE:
return "Apple";
case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA:
return "Nordic Semiconductor ASA";
case BTH_MFG_ARUBA_NETWORKS:
return "Aruba Networks";
case BTH_MFG_INTERNAL_USE:
return "Internal Use";
default:
return "Unknown";
}
}
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/bluetoothradio/option.h"
typedef struct FFBluetoothRadioResult
{
typedef struct FFBluetoothRadioResult {
FFstrbuf name;
FFstrbuf address;
FFstrbuf vendor;
@@ -2,8 +2,8 @@
#include "common/stringUtils.h"
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/io.h"
# include "common/dbus.h"
# include "common/io.h"
/* Example dbus reply:
array [
@@ -34,62 +34,61 @@ array [
]
*/
static const char* detectBluetoothProperty(FFBluetoothRadioResult* device, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
static const char* detectBluetoothProperty(FFBluetoothRadioResult* device, FFDBusData* dbus, DBusMessageIter* iter) {
if (dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) {
return "Expected dict entry";
}
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
if (dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) {
return "Expected dict entry key to be a string";
}
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(ffStrEquals(deviceProperty, "Address"))
if (ffStrEquals(deviceProperty, "Address")) {
ffDBusGetString(dbus, &dictIter, &device->address);
else if(ffStrEquals(deviceProperty, "Alias"))
} else if (ffStrEquals(deviceProperty, "Alias")) {
ffDBusGetString(dbus, &dictIter, &device->name);
else if(ffStrEquals(deviceProperty, "Manufacturer"))
{
} else if (ffStrEquals(deviceProperty, "Manufacturer")) {
uint32_t vendorId;
if (ffDBusGetUint(dbus, &dictIter, &vendorId))
if (ffDBusGetUint(dbus, &dictIter, &vendorId)) {
ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(vendorId));
}
else if(ffStrEquals(deviceProperty, "Version"))
}
} else if (ffStrEquals(deviceProperty, "Version")) {
ffDBusGetUint(dbus, &dictIter, (uint32_t*) &device->lmpVersion);
else if(ffStrEquals(deviceProperty, "Powered"))
} else if (ffStrEquals(deviceProperty, "Powered")) {
ffDBusGetBool(dbus, &dictIter, &device->enabled);
else if(ffStrEquals(deviceProperty, "Discoverable"))
} else if (ffStrEquals(deviceProperty, "Discoverable")) {
ffDBusGetBool(dbus, &dictIter, &device->discoverable);
else if(ffStrEquals(deviceProperty, "Pairable"))
} else if (ffStrEquals(deviceProperty, "Pairable")) {
ffDBusGetBool(dbus, &dictIter, &device->connectable);
}
return NULL;
}
static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const char* hciName, FFDBusData* dbus)
{
static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const char* hciName, FFDBusData* dbus) {
char objPath[300];
snprintf(objPath, sizeof(objPath), "/org/bluez/%s", hciName);
DBusMessage* properties = ffDBusGetMethodReply(dbus, "org.bluez", objPath, "org.freedesktop.DBus.Properties", "GetAll", "org.bluez.Adapter1", NULL);
if(!properties)
if (!properties) {
return "Failed to call org.freedesktop.DBus.Properties.GetAll";
}
DBusMessageIter rootIter;
if(!dbus->lib->ffdbus_message_iter_init(properties, &rootIter))
{
if (!dbus->lib->ffdbus_message_iter_init(properties, &rootIter)) {
dbus->lib->ffdbus_message_unref(properties);
return "Failed to get root iterator of org.freedesktop.DBus.Properties.GetAll";
}
if(dbus->lib->ffdbus_message_iter_get_arg_type(&rootIter) != DBUS_TYPE_ARRAY)
{
if (dbus->lib->ffdbus_message_iter_get_arg_type(&rootIter) != DBUS_TYPE_ARRAY) {
dbus->lib->ffdbus_message_unref(properties);
return "Expected array";
}
@@ -97,8 +96,7 @@ static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const cha
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&rootIter, &arrayIter);
do
{
do {
detectBluetoothProperty(device, dbus, &arrayIter);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
@@ -106,25 +104,27 @@ static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const cha
return NULL;
}
static const char* detectBluetooth(FFlist* devices)
{
static const char* detectBluetooth(FFlist* devices) {
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
if(dirp == NULL)
if (dirp == NULL) {
return "Failed to open /sys/class/bluetooth";
}
FF_DBUS_AUTO_DESTROY_DATA FFDBusData dbus = {};
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
if (error) {
return error;
}
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
if (strchr(entry->d_name, ':') != NULL) // ignore connected devices
if (strchr(entry->d_name, ':') != NULL) { // ignore connected devices
continue;
}
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
@@ -140,12 +140,11 @@ static const char* detectBluetooth(FFlist* devices)
#endif
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
{
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
#else
FF_UNUSED(devices)
return "Fastfetch was compiled without DBus support";
#endif
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) {
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
#else
FF_UNUSED(devices)
return "Fastfetch was compiled without DBus support";
#endif
}
@@ -1,6 +1,5 @@
#include "bluetoothradio.h"
const char* ffDetectBluetoothRadio(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothRadioResult */)
{
const char* ffDetectBluetoothRadio(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothRadioResult */) {
return "Not supported on this platform";
}
@@ -9,13 +9,12 @@
// #include <bthioctl.h>
#define BTH_IOCTL_BASE 0
#define BTH_CTL(id) CTL_CODE(FILE_DEVICE_BLUETOOTH, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_BTH_GET_LOCAL_INFO BTH_CTL(BTH_IOCTL_BASE+0x00)
#define LMP_LE_SUPPORTED(x) ((x >> 38) & 1)
#define BTH_IOCTL_BASE 0
#define BTH_CTL(id) CTL_CODE(FILE_DEVICE_BLUETOOTH, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_BTH_GET_LOCAL_INFO BTH_CTL(BTH_IOCTL_BASE + 0x00)
#define LMP_LE_SUPPORTED(x) ((x >> 38) & 1)
typedef struct _BTH_RADIO_INFO
{
typedef struct _BTH_RADIO_INFO {
// Supported LMP features of the radio. Use LMP_XXX() to extract
// the desired bits.
ULONGLONG lmpSupportedFeatures;
@@ -30,10 +29,9 @@ typedef struct _BTH_RADIO_INFO
UCHAR lmpVersion;
} __attribute__((__packed__)) BTH_RADIO_INFO;
typedef struct _BTH_LOCAL_RADIO_INFO
{
typedef struct _BTH_LOCAL_RADIO_INFO {
// Local BTH_ADDR, class of device, and radio name
BTH_DEVICE_INFO localInfo;
BTH_DEVICE_INFO localInfo;
// Combo of LOCAL_RADIO_XXX values
ULONG flags;
@@ -51,8 +49,7 @@ static_assert(sizeof(BTH_LOCAL_RADIO_INFO) == 292, "BTH_LOCAL_RADIO_INFO should
#pragma GCC diagnostic ignored "-Wpointer-sign"
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
{
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) {
// Actually bluetoothapis.dll, but it's missing on Windows 7
FF_LIBRARY_LOAD_MESSAGE(bluetoothapis, "bluetoothapis.dll", 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio)
@@ -63,33 +60,28 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
HANDLE hRadio = NULL;
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstRadio(&(BLUETOOTH_FIND_RADIO_PARAMS) {
.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS)
}, &hRadio);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS)},
&hRadio);
if (!hFind) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
return "No Bluetooth radios found or service disabled";
else
} else {
return "BluetoothFindFirstRadio() failed";
}
}
do {
BTH_LOCAL_RADIO_INFO blri;
DWORD returned;
if (!DeviceIoControl(hRadio, IOCTL_BTH_GET_LOCAL_INFO, NULL, 0, &blri, sizeof(blri), &returned, NULL))
if (!DeviceIoControl(hRadio, IOCTL_BTH_GET_LOCAL_INFO, NULL, 0, &blri, sizeof(blri), &returned, NULL)) {
continue;
}
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, blri.localInfo.name);
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X",
addr.rgBytes[5],
addr.rgBytes[4],
addr.rgBytes[3],
addr.rgBytes[2],
addr.rgBytes[1],
addr.rgBytes[0]);
BLUETOOTH_ADDRESS_STRUCT addr = {.ullLong = blri.localInfo.address};
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X", addr.rgBytes[5], addr.rgBytes[4], addr.rgBytes[3], addr.rgBytes[2], addr.rgBytes[1], addr.rgBytes[0]);
device->lmpVersion = blri.radioInfo.lmpVersion;
device->lmpSubversion = blri.radioInfo.lmpSubversion;
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/board/option.h"
typedef struct FFBoardResult
{
typedef struct FFBoardResult {
FFstrbuf name;
FFstrbuf vendor;
FFstrbuf version;
+3 -3
View File
@@ -1,9 +1,9 @@
#include "board.h"
#include "common/settings.h"
const char* ffDetectBoard(FFBoardResult* board)
{
if (!ffSettingsGetAndroidProperty("ro.product.board", &board->name))
const char* ffDetectBoard(FFBoardResult* board) {
if (!ffSettingsGetAndroidProperty("ro.product.board", &board->name)) {
ffSettingsGetAndroidProperty("ro.board.platform", &board->name);
}
return NULL;
}
+11 -9
View File
@@ -2,29 +2,31 @@
#include "common/apple/cf_helpers.h"
const char* ffDetectBoard(FFBoardResult* result)
{
const char* ffDetectBoard(FFBoardResult* result) {
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("IOPlatformExpertDevice"));
if (!service)
if (!service) {
return "No IOPlatformExpertDevice found";
}
FF_CFTYPE_AUTO_RELEASE CFTypeRef boardId = IORegistryEntryCreateCFProperty(service, CFSTR("board-id"), kCFAllocatorDefault, kNilOptions);
if (boardId)
if (boardId) {
ffCfStrGetString(boardId, &result->name);
else
{
} else {
io_name_t name;
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess) {
ffStrbufSetS(&result->name, name);
}
}
FF_CFTYPE_AUTO_RELEASE CFStringRef version = IORegistryEntryCreateCFProperty(service, CFSTR("version"), kCFAllocatorDefault, kNilOptions);
if (version)
if (version) {
ffCfStrGetString(version, &result->version);
}
FF_CFTYPE_AUTO_RELEASE CFTypeRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
if (manufacturer)
if (manufacturer) {
ffCfStrGetString(manufacturer, &result->vendor);
}
return NULL;
}
+1 -2
View File
@@ -2,8 +2,7 @@
#include "common/settings.h"
#include "common/smbiosHelper.h"
const char* ffDetectBoard(FFBoardResult* result)
{
const char* ffDetectBoard(FFBoardResult* result) {
ffSettingsGetFreeBSDKenv("smbios.planar.product", &result->name);
ffCleanUpSmbiosValue(&result->name);
ffSettingsGetFreeBSDKenv("smbios.planar.serial", &result->serial);
+8 -16
View File
@@ -2,29 +2,21 @@
#include "common/io.h"
#include "common/smbiosHelper.h"
const char* ffDetectBoard(FFBoardResult* board)
{
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name))
{
const char* ffDetectBoard(FFBoardResult* board) {
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name)) {
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_serial", "/sys/class/dmi/id/board_serial", &board->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version);
}
else if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/baseboard/product", &board->name))
{
} else if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/baseboard/product", &board->name)) {
ffStrbufTrimRight(&board->name, '\0');
if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/baseboard/manufacturer", &board->vendor))
if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/baseboard/manufacturer", &board->vendor)) {
ffStrbufTrimRight(&board->vendor, '\0');
}
else if (ffReadFileBuffer("/sys/firmware/devicetree/base/board", &board->name))
{
}
} else if (ffReadFileBuffer("/sys/firmware/devicetree/base/board", &board->name)) {
ffStrbufTrimRightSpace(&board->name);
}
else if (ffReadFileBuffer("/sys/firmware/devicetree/base/compatible", &board->vendor))
{
} else if (ffReadFileBuffer("/sys/firmware/devicetree/base/compatible", &board->vendor)) {
uint32_t comma = ffStrbufFirstIndexC(&board->vendor, ',');
if (comma < board->vendor.length)
{
if (comma < board->vendor.length) {
ffStrbufSetS(&board->name, board->vendor.chars + comma + 1);
ffStrbufTrimRightSpace(&board->name);
ffStrbufSubstrBefore(&board->vendor, comma);
+9 -6
View File
@@ -2,16 +2,19 @@
#include "common/sysctl.h"
#include "common/smbiosHelper.h"
const char* ffDetectBoard(FFBoardResult* board)
{
if (ffSysctlGetString("machdep.dmi.board-product", &board->name) == NULL)
const char* ffDetectBoard(FFBoardResult* board) {
if (ffSysctlGetString("machdep.dmi.board-product", &board->name) == NULL) {
ffCleanUpSmbiosValue(&board->name);
if (ffSysctlGetString("machdep.dmi.board-version", &board->version) == NULL)
}
if (ffSysctlGetString("machdep.dmi.board-version", &board->version) == NULL) {
ffCleanUpSmbiosValue(&board->version);
if (ffSysctlGetString("machdep.dmi.board-vendor", &board->vendor) == NULL)
}
if (ffSysctlGetString("machdep.dmi.board-vendor", &board->vendor) == NULL) {
ffCleanUpSmbiosValue(&board->vendor);
if (ffSysctlGetString("machdep.dmi.board-serial", &board->serial) == NULL)
}
if (ffSysctlGetString("machdep.dmi.board-serial", &board->serial) == NULL) {
ffCleanUpSmbiosValue(&board->serial);
}
return NULL;
}
+1 -2
View File
@@ -1,6 +1,5 @@
#include "board.h"
const char* ffDetectBoard(FF_MAYBE_UNUSED FFBoardResult* board)
{
const char* ffDetectBoard(FF_MAYBE_UNUSED FFBoardResult* board) {
return "Not supported on this platform";
}
+16 -16
View File
@@ -1,35 +1,35 @@
#include "board.h"
#include "common/smbiosHelper.h"
typedef struct FFSmbiosBaseboard
{
typedef struct FFSmbiosBaseboard {
FFSmbiosHeader Header;
uint8_t Manufacturer; // string
uint8_t Product; // string
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t AssetTag; // string
uint8_t FeatureFlags; // bit field
uint8_t LocationInChassis; // string
uint16_t ChassisHandle; // varies
uint8_t BoardType; // enum
uint8_t Manufacturer; // string
uint8_t Product; // string
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t AssetTag; // string
uint8_t FeatureFlags; // bit field
uint8_t LocationInChassis; // string
uint16_t ChassisHandle; // varies
uint8_t BoardType; // enum
uint8_t NumberOfContainedObjectHandles; // varies
uint16_t ContainedObjectHandles[]; // varies
uint16_t ContainedObjectHandles[]; // varies
} __attribute__((__packed__)) FFSmbiosBaseboard;
static_assert(offsetof(FFSmbiosBaseboard, ContainedObjectHandles) == 0x0F,
"FFSmbiosBaseboard: Wrong struct alignment");
const char* ffDetectBoard(FFBoardResult* board)
{
const char* ffDetectBoard(FFBoardResult* board) {
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
if (!smbiosTable)
if (!smbiosTable) {
return "Failed to get SMBIOS data";
}
const FFSmbiosBaseboard* data = (const FFSmbiosBaseboard*) (*smbiosTable)[FF_SMBIOS_TYPE_BASEBOARD_INFO];
if (!data)
if (!data) {
return "Baseboard information section is not found in SMBIOS data";
}
const char* strings = (const char*) data + data->Header.Length;
+14 -20
View File
@@ -1,23 +1,17 @@
#include "efi_helper.h"
static inline uint8_t evBits(uint16_t val, uint8_t mask, uint8_t shift)
{
static inline uint8_t evBits(uint16_t val, uint8_t mask, uint8_t shift) {
return (uint8_t) ((val & (mask << shift)) >> shift);
}
static void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result)
{
for (uint32_t i = 0; chars[i]; i++)
{
if (chars[i] <= 0x007f)
static void ffEfiUcs2ToUtf8(const uint16_t* const chars, FFstrbuf* result) {
for (uint32_t i = 0; chars[i]; i++) {
if (chars[i] <= 0x007f) {
ffStrbufAppendC(result, (char) chars[i]);
else if (chars[i] > 0x007f && chars[i] <= 0x07ff)
{
} else if (chars[i] > 0x007f && chars[i] <= 0x07ff) {
ffStrbufAppendC(result, (char) (0xc0 | evBits(chars[i], 0x1f, 6)));
ffStrbufAppendC(result, (char) (0x80 | evBits(chars[i], 0x3f, 0)));
}
else
{
} else {
ffStrbufAppendC(result, (char) (0xe0 | evBits(chars[i], 0xf, 12)));
ffStrbufAppendC(result, (char) (0x80 | evBits(chars[i], 0x3f, 6)));
ffStrbufAppendC(result, (char) (0x80 | evBits(chars[i], 0x3f, 0)));
@@ -25,21 +19,21 @@ static void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result)
}
}
bool ffEfiFillLoadOption(const FFEfiLoadOption* efiOption, FFBootmgrResult* result)
{
bool ffEfiFillLoadOption(const FFEfiLoadOption* efiOption, FFBootmgrResult* result) {
uint32_t descLen = 0;
while (efiOption->Description[descLen]) ++descLen;
while (efiOption->Description[descLen]) {
++descLen;
}
if (descLen)
if (descLen) {
ffEfiUcs2ToUtf8(efiOption->Description, &result->name);
}
for (
ffEfiDevicePathProtocol* filePathList = (ffEfiDevicePathProtocol*) &efiOption->Description[descLen + 1];
filePathList->Type != 0x7F; // End of Hardware Device Path
filePathList = (ffEfiDevicePathProtocol*) ((uint8_t*) filePathList + filePathList->Length))
{
if (filePathList->Type == 4 && filePathList->SubType == 4)
{
filePathList = (ffEfiDevicePathProtocol*) ((uint8_t*) filePathList + filePathList->Length)) {
if (filePathList->Type == 4 && filePathList->SubType == 4) {
// https://uefi.org/specs/UEFI/2.10/10_Protocols_Device_Path_Protocol.html#file-path-media-device-path
ffEfiUcs2ToUtf8((uint16_t*) filePathList->SpecificDevicePathData, &result->firmware);
return true;
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/bootmgr/option.h"
typedef struct FFBootmgrResult
{
typedef struct FFBootmgrResult {
FFstrbuf name;
FFstrbuf firmware;
uint16_t order;
+19 -14
View File
@@ -4,43 +4,48 @@
#include <IOKit/IOKitLib.h>
static const char* detectSecureBoot(bool* result)
{
#if __aarch64__
static const char* detectSecureBoot(bool* result) {
#if __aarch64__
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen");
if (!entryDevice)
if (!entryDevice) {
return "IORegistryEntryFromPath() failed";
}
FF_CFTYPE_AUTO_RELEASE CFTypeRef prop = IORegistryEntryCreateCFProperty(entryDevice, CFSTR("secure-boot"), kCFAllocatorDefault, 0);
if (!prop)
if (!prop) {
return "IORegistryEntryCreateCFProperty() failed";
}
if (CFGetTypeID(prop) != CFDataGetTypeID() || CFDataGetLength((CFDataRef) prop) == 0)
if (CFGetTypeID(prop) != CFDataGetTypeID() || CFDataGetLength((CFDataRef) prop) == 0) {
return "Invalid secure-boot property";
}
*result = (bool) *CFDataGetBytePtr((CFDataRef) prop);
#else
#else
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/options");
if (!entryDevice)
if (!entryDevice) {
return "IORegistryEntryFromPath() failed";
}
FF_CFTYPE_AUTO_RELEASE CFTypeRef prop = IORegistryEntryCreateCFProperty(entryDevice, CFSTR("94b73556-2197-4702-82a8-3e1337dafbfb:AppleSecureBootPolicy"), kCFAllocatorDefault, 0);
if (!prop)
if (!prop) {
return "IORegistryEntryCreateCFProperty() failed";
}
if (CFGetTypeID(prop) != CFDataGetTypeID() || CFDataGetLength((CFDataRef) prop) == 0)
if (CFGetTypeID(prop) != CFDataGetTypeID() || CFDataGetLength((CFDataRef) prop) == 0) {
return "Invalid secure-boot property";
}
*result = *CFDataGetBytePtr((CFDataRef) prop) != 0x02 /* Permissive Security */;
#endif
#endif
return NULL;
}
const char* ffDetectBootmgr(FFBootmgrResult* result)
{
if (ffPathExists("/System/Library/CoreServices/boot.efi", FF_PATHTYPE_FILE))
const char* ffDetectBootmgr(FFBootmgrResult* result) {
if (ffPathExists("/System/Library/CoreServices/boot.efi", FF_PATHTYPE_FILE)) {
ffStrbufSetStatic(&result->firmware, "/System/Library/CoreServices/boot.efi");
}
ffStrbufSetStatic(&result->name, "iBoot");
+19 -15
View File
@@ -3,26 +3,27 @@
#include "common/io.h"
#ifdef __OpenBSD__
#include <dev/efi/efiio.h>
# include <dev/efi/efiio.h>
#else
#include <sys/efiio.h>
# include <sys/efiio.h>
#endif
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdalign.h>
#ifdef __NetBSD__
typedef uint16_t efi_char;
typedef uint16_t efi_char;
#endif
#ifndef EFI_GLOBAL_VARIABLE
#define EFI_GLOBAL_VARIABLE { 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, { 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } }
# define EFI_GLOBAL_VARIABLE {0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, {0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c}}
#endif
const char* ffDetectBootmgr(FFBootmgrResult* result)
{
const char* ffDetectBootmgr(FFBootmgrResult* result) {
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR | O_CLOEXEC);
if (efifd < 0) return "open(/dev/efi) failed";
if (efifd < 0) {
return "open(/dev/efi) failed";
}
alignas(uint16_t) uint8_t buffer[2048];
struct efi_var_ioc ioc = {
@@ -31,28 +32,31 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
};
ioc.datasize = sizeof(buffer);
ioc.name = (efi_char[]){ 'B', 'o', 'o', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', '\0' };
ioc.name = (efi_char[]) {'B', 'o', 'o', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', '\0'};
ioc.namesize = sizeof("BootCurrent") * 2;
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize != 2)
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize != 2) {
return "ioctl(EFIIOC_VAR_GET, BootCurrent) failed";
}
result->order = *(uint16_t*)buffer;
result->order = *(uint16_t*) buffer;
unsigned char hex[5];
snprintf((char*) hex, sizeof(hex), "%04X", result->order);
ioc.datasize = sizeof(buffer);
ioc.name = (efi_char[]){ 'B', 'o', 'o', 't', hex[0], hex[1], hex[2], hex[3], '\0' };
ioc.name = (efi_char[]) {'B', 'o', 'o', 't', hex[0], hex[1], hex[2], hex[3], '\0'};
ioc.namesize = sizeof("Boot####") * 2;
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize == sizeof(buffer))
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize == sizeof(buffer)) {
return "ioctl(EFIIOC_VAR_GET, Boot####) failed";
}
ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result);
ffEfiFillLoadOption((FFEfiLoadOption*) buffer, result);
ioc.name = (efi_char[]){ 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', '\0' };
ioc.name = (efi_char[]) {'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', '\0'};
ioc.namesize = sizeof("SecureBoot") * 2;
ioc.datasize = sizeof(buffer);
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) == 0 && ioc.datasize == 1)
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) == 0 && ioc.datasize == 1) {
result->secureBoot = !!buffer[0];
}
return NULL;
}
+9 -8
View File
@@ -6,26 +6,27 @@
#define FF_EFIVARS_PATH_PREFIX "/sys/firmware/efi/efivars/"
const char* ffDetectBootmgr(FFBootmgrResult* result)
{
const char* ffDetectBootmgr(FFBootmgrResult* result) {
alignas(uint16_t) uint8_t buffer[2048];
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "BootCurrent-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) != 6)
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "BootCurrent-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) != 6) {
return "Failed to read efivar: BootCurrent";
}
result->order = *(uint16_t *)&buffer[4];
result->order = *(uint16_t*) &buffer[4];
snprintf((char*) buffer, sizeof(buffer), FF_EFIVARS_PATH_PREFIX "Boot%04X-" FF_EFI_GLOBAL_GUID, result->order);
ssize_t size = ffReadFileData((const char*) buffer, sizeof(buffer), buffer);
if (size < 5 + (int) sizeof(FFEfiLoadOption) || size == (ssize_t) sizeof(buffer))
if (size < 5 + (int) sizeof(FFEfiLoadOption) || size == (ssize_t) sizeof(buffer)) {
return "Failed to read efivar: Boot####";
}
ffEfiFillLoadOption((FFEfiLoadOption *)&buffer[4], result);
ffEfiFillLoadOption((FFEfiLoadOption*) &buffer[4], result);
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) >= 5)
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) >= 5) {
result->secureBoot = buffer[4] == 1;
}
return NULL;
}
+1 -2
View File
@@ -1,6 +1,5 @@
#include "bootmgr.h"
const char* ffDetectBootmgr(FF_MAYBE_UNUSED FFBootmgrResult* result)
{
const char* ffDetectBootmgr(FF_MAYBE_UNUSED FFBootmgrResult* result) {
return "Not supported on this platform";
}
+26 -18
View File
@@ -6,61 +6,69 @@
#include <ntstatus.h>
#include <windows.h>
const char* enablePrivilege(const wchar_t* privilege)
{
const char* enablePrivilege(const wchar_t* privilege) {
FF_AUTO_CLOSE_FD HANDLE token = NULL;
if (!NT_SUCCESS(NtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)))
if (!NT_SUCCESS(NtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))) {
return "NtOpenProcessToken() failed";
}
TOKEN_PRIVILEGES tp = {
.PrivilegeCount = 1,
.Privileges = {
(LUID_AND_ATTRIBUTES) { .Attributes = SE_PRIVILEGE_ENABLED }
},
(LUID_AND_ATTRIBUTES) {.Attributes = SE_PRIVILEGE_ENABLED}},
};
if (!LookupPrivilegeValueW(NULL, privilege, &tp.Privileges[0].Luid))
if (!LookupPrivilegeValueW(NULL, privilege, &tp.Privileges[0].Luid)) {
return "LookupPrivilegeValue() failed";
}
NTSTATUS status = NtAdjustPrivilegesToken(token, false, &tp, sizeof(tp), NULL, NULL);
if (!NT_SUCCESS(status))
if (!NT_SUCCESS(status)) {
return "NtAdjustPrivilegesToken() failed";
}
if (status == STATUS_NOT_ALL_ASSIGNED)
if (status == STATUS_NOT_ALL_ASSIGNED) {
return "The token does not have the specified privilege; try sudo please";
}
return NULL;
}
const char* ffDetectBootmgr(FFBootmgrResult* result)
{
const char* ffDetectBootmgr(FFBootmgrResult* result) {
const char* err = enablePrivilege(L"SeSystemEnvironmentPrivilege");
if (err != NULL)
if (err != NULL) {
return err;
}
GUID efiGlobalGuid;
if (!NT_SUCCESS(RtlGUIDFromString(&(UNICODE_STRING) RTL_CONSTANT_STRING(L"{" FF_EFI_GLOBAL_GUID L"}"), &efiGlobalGuid)))
if (!NT_SUCCESS(RtlGUIDFromString(&(UNICODE_STRING) RTL_CONSTANT_STRING(L"{" FF_EFI_GLOBAL_GUID L"}"), &efiGlobalGuid))) {
return "RtlGUIDFromString() failed";
}
ULONG size = sizeof(result->order);
if (!NT_SUCCESS(NtQuerySystemEnvironmentValueEx(&(UNICODE_STRING) RTL_CONSTANT_STRING(L"BootCurrent"), &efiGlobalGuid, &result->order, &size, NULL)))
if (!NT_SUCCESS(NtQuerySystemEnvironmentValueEx(&(UNICODE_STRING) RTL_CONSTANT_STRING(L"BootCurrent"), &efiGlobalGuid, &result->order, &size, NULL))) {
return "NtQuerySystemEnvironmentValueEx(BootCurrent) failed";
if (size != sizeof(result->order))
}
if (size != sizeof(result->order)) {
return "NtQuerySystemEnvironmentValueEx(BootCurrent) returned unexpected size";
}
uint8_t buffer[2048];
wchar_t key[9];
swprintf(key, ARRAY_SIZE(key), L"Boot%04X", result->order);
size = sizeof(buffer);
if (!NT_SUCCESS(NtQuerySystemEnvironmentValueEx(&(UNICODE_STRING) RTL_CONSTANT_STRING(key), &efiGlobalGuid, buffer, &size, NULL)))
if (!NT_SUCCESS(NtQuerySystemEnvironmentValueEx(&(UNICODE_STRING) RTL_CONSTANT_STRING(key), &efiGlobalGuid, buffer, &size, NULL))) {
return "NtQuerySystemEnvironmentValueEx(Boot####) failed";
if (size < sizeof(FFEfiLoadOption) || size == ARRAY_SIZE(buffer))
}
if (size < sizeof(FFEfiLoadOption) || size == ARRAY_SIZE(buffer)) {
return "NtQuerySystemEnvironmentValueEx(Boot####) returned unexpected size";
}
ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result);
ffEfiFillLoadOption((FFEfiLoadOption*) buffer, result);
SYSTEM_SECUREBOOT_INFORMATION ssi;
if (NT_SUCCESS(NtQuerySystemInformation(SystemSecureBootInformation, &ssi, sizeof(ssi), NULL)))
if (NT_SUCCESS(NtQuerySystemInformation(SystemSecureBootInformation, &ssi, sizeof(ssi), NULL))) {
result->secureBoot = ssi.SecureBootEnabled;
}
return NULL;
}
+2 -4
View File
@@ -1,8 +1,7 @@
#include "bootmgr.h"
// https://uefi.org/specs/UEFI/2.10/10_Protocols_Device_Path_Protocol.html#generic-device-path-structures
typedef struct ffEfiDevicePathProtocol
{
typedef struct ffEfiDevicePathProtocol {
uint8_t Type;
uint8_t SubType;
uint16_t Length;
@@ -10,8 +9,7 @@ typedef struct ffEfiDevicePathProtocol
} ffEfiDevicePathProtocol;
// https://uefi.org/specs/UEFI/2.10/03_Boot_Manager.html#load-options
typedef struct FFEfiLoadOption
{
typedef struct FFEfiLoadOption {
uint32_t Attributes;
uint16_t FilePathListLength;
uint16_t Description[];
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/brightness/option.h"
typedef struct FFBrightnessResult
{
typedef struct FFBrightnessResult {
FFstrbuf name;
double min, max, current;
bool builtin;
+67 -61
View File
@@ -15,28 +15,25 @@ extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress,
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import));
#else
// DDC/CI (Intel)
#include <IOKit/IOKitLib.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <IOKit/i2c/IOI2CInterface.h>
# include <IOKit/IOKitLib.h>
# include <IOKit/graphics/IOGraphicsLib.h>
# include <IOKit/i2c/IOI2CInterface.h>
extern void CGSServiceForDisplayNumber(CGDirectDisplayID display, io_service_t* service) __attribute__((weak_import));
#endif
// ACPI
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float* brightness) __attribute__((weak_import));
// Works for internal display
static const char* detectWithDisplayServices(const FFDisplayServerResult* displayServer, FFlist* result)
{
if(DisplayServicesGetBrightness == NULL)
static const char* detectWithDisplayServices(const FFDisplayServerResult* displayServer, FFlist* result) {
if (DisplayServicesGetBrightness == NULL) {
return "DisplayServices function DisplayServicesGetBrightness is not available";
}
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN)
{
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN) {
float value;
if(DisplayServicesGetBrightness((CGDirectDisplayID) display->id, &value) == kCGErrorSuccess)
{
if (DisplayServicesGetBrightness((CGDirectDisplayID) display->id, &value) == kCGErrorSuccess) {
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->current = value;
brightness->max = 1;
@@ -53,56 +50,55 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
#ifdef __aarch64__
// https://github.com/waydabber/m1ddc
// Works for Apple Silicon and USB-C adapter connection ( but not HTMI )
static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!IOAVServiceCreate || !IOAVServiceReadI2C || !IOAVServiceWriteI2C)
static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) {
if (!IOAVServiceCreate || !IOAVServiceReadI2C || !IOAVServiceWriteI2C) {
return "IOAVService is not available";
}
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess) {
return "IOServiceGetMatchingServices() failed";
}
io_registry_entry_t registryEntry;
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = NULL;
{
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))
{
if (IOAVServiceUserInterfaceSupported && !CFBooleanGetValue(IOAVServiceUserInterfaceSupported)) {
// IOAVServiceCreateWithService won't work
continue;
}
FF_CFTYPE_AUTO_RELEASE CFStringRef location = IORegistryEntryCreateCFProperty(entryAv, CFSTR("Location"), kCFAllocatorDefault, kNilOptions);
if (location && CFStringCompare(location, CFSTR("Embedded"), 0) == 0)
{
if (location && CFStringCompare(location, CFSTR("Embedded"), 0) == 0) {
// Builtin display should be handled by DisplayServices
continue;
}
service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
if (!service) continue;
if (!service) {
continue;
}
}
{
uint8_t i2cIn[4] = { 0x82, 0x01, 0x10 /* luminance */ };
uint8_t i2cIn[4] = {0x82, 0x01, 0x10 /* luminance */};
i2cIn[3] = 0x6e ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2];
for (uint32_t i = 0; i < 2; ++i)
{
for (uint32_t i = 0; i < 2; ++i) {
IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, ARRAY_SIZE(i2cIn));
usleep(options->ddcciSleep * 1000);
}
}
uint8_t i2cOut[12] = {};
if (IOAVServiceReadI2C(service, 0x37, 0x51, i2cOut, ARRAY_SIZE(i2cOut)) == KERN_SUCCESS)
{
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00)
if (IOAVServiceReadI2C(service, 0x37, 0x51, i2cOut, ARRAY_SIZE(i2cOut)) == KERN_SUCCESS) {
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) {
continue;
}
uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9];
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
@@ -115,37 +111,38 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
brightness->builtin = false;
uint8_t edid[128] = {};
if (IOAVServiceReadI2C(service, 0x50, 0x00, edid, ARRAY_SIZE(edid)) == KERN_SUCCESS)
if (IOAVServiceReadI2C(service, 0x50, 0x00, edid, ARRAY_SIZE(edid)) == KERN_SUCCESS) {
ffEdidGetName(edid, &brightness->name);
}
}
}
return NULL;
}
#else
static IOOptionBits getSupportedTransactionType(void)
{
static IOOptionBits getSupportedTransactionType(void) {
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("IOFramebufferI2CInterface"), &iterator) != KERN_SUCCESS)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("IOFramebufferI2CInterface"), &iterator) != KERN_SUCCESS) {
return kIOI2CNoTransactionType;
}
io_registry_entry_t registryEntry;
while ((registryEntry = IOIteratorNext(iterator)) != MACH_PORT_NULL)
{
while ((registryEntry = IOIteratorNext(iterator)) != MACH_PORT_NULL) {
FF_IOOBJECT_AUTO_RELEASE io_service_t io_service = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFNumberRef IOI2CTransactionTypes = IORegistryEntryCreateCFProperty(io_service, CFSTR(kIOI2CTransactionTypesKey), kCFAllocatorDefault, kNilOptions);
if (IOI2CTransactionTypes)
{
if (IOI2CTransactionTypes) {
int64_t types = 0;
ffCfNumGetInt64(IOI2CTransactionTypes, &types);
if (types) {
if ((1 << kIOI2CDDCciReplyTransactionType) & (uint64_t) types)
if ((1 << kIOI2CDDCciReplyTransactionType) & (uint64_t) types) {
return kIOI2CDDCciReplyTransactionType;
if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types)
}
if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types) {
return kIOI2CSimpleTransactionType;
}
}
}
break;
@@ -154,36 +151,41 @@ static IOOptionBits getSupportedTransactionType(void)
return kIOI2CNoTransactionType;
}
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available";
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) {
if (!CGSServiceForDisplayNumber) {
return "CGSServiceForDisplayNumber is not available";
}
IOOptionBits transactionType = getSupportedTransactionType();
if (transactionType == kIOI2CNoTransactionType)
if (transactionType == kIOI2CNoTransactionType) {
return "No supported IOI2C transaction type found";
}
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_EXTERNAL)
{
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
if (display->type == FF_DISPLAY_TYPE_EXTERNAL) {
FF_IOOBJECT_AUTO_RELEASE io_service_t framebuffer = IO_OBJECT_NULL;
CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer);
if (framebuffer == IO_OBJECT_NULL) continue;
CGSServiceForDisplayNumber((CGDirectDisplayID) display->id, &framebuffer);
if (framebuffer == IO_OBJECT_NULL) {
continue;
}
IOItemCount count;
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0)
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) {
continue;
}
for (IOItemCount bus = 0; bus < count; ++bus)
{
for (IOItemCount bus = 0; bus < count; ++bus) {
FF_IOOBJECT_AUTO_RELEASE io_service_t interface = IO_OBJECT_NULL;
if (IOFBCopyI2CInterfaceForBus(framebuffer, bus, &interface) != KERN_SUCCESS) continue;
if (IOFBCopyI2CInterfaceForBus(framebuffer, bus, &interface) != KERN_SUCCESS) {
continue;
}
uint8_t i2cOut[12] = {};
IOI2CConnectRef connect = NULL;
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS)
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) {
continue;
}
uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 };
uint8_t i2cIn[] = {0x51, 0x82, 0x01, 0x10 /* luminance */, 0};
i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3];
IOI2CRequest request = {
@@ -202,8 +204,12 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
IOI2CInterfaceClose(connect, kNilOptions);
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess || request.replyBytes < 10) continue;
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue;
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess || request.replyBytes < 10) {
continue;
}
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) {
continue;
}
uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9];
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
@@ -224,14 +230,14 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
}
#endif
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result)
{
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result) {
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
detectWithDisplayServices(displayServer, result);
if (displayServer->displays.length > result->length)
if (displayServer->displays.length > result->length) {
detectWithDdcci(displayServer, options, result);
}
return NULL;
}
+15 -15
View File
@@ -2,29 +2,29 @@
#if __has_include(<sys/backlight.h>)
#include "common/io.h"
# include "common/io.h"
#include <sys/backlight.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <unistd.h>
# include <sys/backlight.h>
# include <sys/ioctl.h>
# include <sys/fcntl.h>
# include <unistd.h>
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) {
// https://man.freebsd.org/cgi/man.cgi?query=backlight&sektion=9
char path[] = "/dev/backlight/backlight0";
for (char i = '0'; i <= '9'; ++i)
{
for (char i = '0'; i <= '9'; ++i) {
path[ARRAY_SIZE(path) - 2] = i;
FF_AUTO_CLOSE_FD int blfd = open(path, O_RDONLY | O_CLOEXEC);
if (blfd < 0)
if (blfd < 0) {
continue;
}
struct backlight_props status;
if(ioctl(blfd, BACKLIGHTGETSTATUS, &status) < 0)
if (ioctl(blfd, BACKLIGHTGETSTATUS, &status) < 0) {
continue;
}
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInit(&brightness->name);
@@ -35,18 +35,18 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
brightness->builtin = true;
struct backlight_info info;
if(ioctl(blfd, BACKLIGHTGETINFO, &info) == 0)
if (ioctl(blfd, BACKLIGHTGETINFO, &info) == 0) {
ffStrbufAppendS(&brightness->name, info.name);
else
} else {
ffStrbufAppendS(&brightness->name, path + strlen("/dev/backlight/"));
}
}
return NULL;
}
#else
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result)
{
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result) {
return "Backlight is supported only on FreeBSD 13 and newer";
}
+57 -67
View File
@@ -6,14 +6,14 @@
#include <dirent.h>
#include <limits.h>
static const char* detectWithBacklight(FFlist* result)
{
//https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight
static const char* detectWithBacklight(FFlist* result) {
// https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight
const char* backlightDirPath = "/sys/class/backlight/";
DIR* dirp = opendir(backlightDirPath);
if(dirp == NULL)
if (dirp == NULL) {
return "Failed to open `/sys/class/backlight/`";
}
FF_STRBUF_AUTO_DESTROY backlightDir = ffStrbufCreateA(64);
ffStrbufAppendS(&backlightDir, backlightDirPath);
@@ -23,54 +23,46 @@ static const char* detectWithBacklight(FFlist* result)
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
ffStrbufAppendS(&backlightDir, entry->d_name);
ffStrbufAppendS(&backlightDir, "/brightness");
if(ffReadFileBuffer(backlightDir.chars, &buffer))
{
if (ffReadFileBuffer(backlightDir.chars, &buffer)) {
double actualBrightness = ffStrbufToDouble(&buffer, 0);
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
ffStrbufAppendS(&backlightDir, entry->d_name);
ffStrbufAppendS(&backlightDir, "/max_brightness");
if(ffReadFileBuffer(backlightDir.chars, &buffer))
{
if (ffReadFileBuffer(backlightDir.chars, &buffer)) {
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufSubstrBeforeLastC(&backlightDir, '/');
ffStrbufAppendS(&backlightDir, "/device");
ffStrbufInitA(&brightness->name, PATH_MAX);
if(realpath(backlightDir.chars, brightness->name.chars))
{
if (realpath(backlightDir.chars, brightness->name.chars)) {
ffStrbufRecalculateLength(&brightness->name);
// if we managed to get edid, use it
ffStrbufAppendS(&brightness->name, "/edid");
uint8_t edidData[128];
if(ffReadFileData(brightness->name.chars, ARRAY_SIZE(edidData), edidData) == ARRAY_SIZE(edidData))
{
if (ffReadFileData(brightness->name.chars, ARRAY_SIZE(edidData), edidData) == ARRAY_SIZE(edidData)) {
ffStrbufClear(&brightness->name);
ffEdidGetName(edidData, &brightness->name);
}
else
{
} else {
ffStrbufSubstrBeforeLastC(&brightness->name, '/'); // remove "/edid"
ffStrbufSubstrAfterLastC(&brightness->name, '/'); // try getting DRM connector name
if(ffCharIsDigit(brightness->name.chars[0]))
{
ffStrbufSubstrAfterLastC(&brightness->name, '/'); // try getting DRM connector name
if (ffCharIsDigit(brightness->name.chars[0])) {
// PCI address or some unknown path, give up
ffStrbufSetS(&brightness->name, entry->d_name);
}
else
{
if(ffStrbufStartsWithS(&brightness->name, "card") && ffCharIsDigit(brightness->name.chars[4]))
} else {
if (ffStrbufStartsWithS(&brightness->name, "card") && ffCharIsDigit(brightness->name.chars[4])) {
ffStrbufSubstrAfterFirstC(&brightness->name, '-');
}
}
}
}
else
} else {
ffStrbufInitS(&brightness->name, entry->d_name);
}
brightness->max = ffStrbufToDouble(&buffer, 0);
brightness->min = 0;
brightness->current = actualBrightness;
@@ -86,22 +78,21 @@ static const char* detectWithBacklight(FFlist* result)
}
#ifdef FF_HAVE_DDCUTIL
#include "detection/displayserver/displayserver.h"
#include "common/library.h"
#include "common/mallocHelper.h"
# include "detection/displayserver/displayserver.h"
# include "common/library.h"
# include "common/mallocHelper.h"
#include <ddcutil_macros.h>
#include <ddcutil_c_api.h>
# include <ddcutil_macros.h>
# include <ddcutil_c_api.h>
// Try to be compatible with ddcutil 2.0
#if DDCUTIL_VMAJOR >= 2
# if DDCUTIL_VMAJOR >= 2
double ddca_set_default_sleep_multiplier(double multiplier); // ddcutil 1.4
#else
DDCA_Status ddca_init(const char *libopts, int syslog_level, int opts);
#endif
# else
DDCA_Status ddca_init(const char* libopts, int syslog_level, int opts);
# endif
static const char* detectWithDdcci(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
static const char* detectWithDdcci(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(libddcutil, "libddcutil" FF_LIBRARY_EXTENSION, 5);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2)
@@ -109,49 +100,48 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED FFBrightnessOptions* options,
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display)
#ifndef FF_DISABLE_DLOPEN
# ifndef FF_DISABLE_DLOPEN
FF_LIBRARY_LOAD_SYMBOL_LAZY(libddcutil, ddca_init)
if (ffddca_init)
{
if (ffddca_init) {
FF_SUPPRESS_IO();
// Ref: https://github.com/rockowitz/ddcutil/issues/344
if (ffddca_init(NULL, -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0)
if (ffddca_init(NULL, -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0) {
return "ddca_init() failed";
}
else
{
}
} else {
FF_LIBRARY_LOAD_SYMBOL_LAZY(libddcutil, ddca_set_default_sleep_multiplier);
if (ffddca_set_default_sleep_multiplier)
if (ffddca_set_default_sleep_multiplier) {
ffddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0);
}
libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330
}
#else
#if DDCUTIL_VMAJOR >= 2
if (ddca_init(NULL, -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0)
return "ddca_init() failed";
#else
ddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0);
#endif
#endif
# else
# if DDCUTIL_VMAJOR >= 2
if (ddca_init(NULL, -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0) {
return "ddca_init() failed";
}
# else
ddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0);
# endif
# endif
FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL;
if (ffddca_get_display_info_list2(false, &infoList) < 0)
if (ffddca_get_display_info_list2(false, &infoList) < 0) {
return "ddca_get_display_info_list2(false, &infoList) failed";
}
if (infoList->ct == 0)
if (infoList->ct == 0) {
return "No DDC/CI compatible displays found";
}
for (int index = 0; index < infoList->ct; ++index)
{
for (int index = 0; index < infoList->ct; ++index) {
const DDCA_Display_Info* display = &infoList->info[index];
DDCA_Display_Handle handle;
if (ffddca_open_display2(display->dref, false, &handle) >= 0)
{
if (ffddca_open_display2(display->dref, false, &handle) >= 0) {
DDCA_Any_Vcp_Value* vcpValue = NULL;
if (ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0)
{
if (ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0) {
assert(vcpValue->value_type == DDCA_NON_TABLE_VCP_VALUE);
int current = VALREC_CUR_VAL(vcpValue), max = VALREC_MAX_VAL(vcpValue);
ffddca_free_any_vcp_value(vcpValue);
@@ -170,15 +160,15 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED FFBrightnessOptions* options,
}
#endif
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) {
detectWithBacklight(result);
#ifdef FF_HAVE_DDCUTIL
#ifdef FF_HAVE_DDCUTIL
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
if (result->length < displayServer->displays.length)
if (result->length < displayServer->displays.length) {
detectWithDdcci(options, result);
#endif
}
#endif
return NULL;
}
+5 -5
View File
@@ -2,17 +2,17 @@
#include "common/sysctl.h"
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) {
// https://man.netbsd.org/NetBSD-10.1/acpiout.4#DESCRIPTION
char key[] = "hw.acpi.acpiout0.brightness";
char* pn = key + strlen("hw.acpi.acpiout");
for (uint32_t i = 0; i <= 9; ++i)
{
for (uint32_t i = 0; i <= 9; ++i) {
*pn = (char) ('0' + i);
int value = ffSysctlGetInt(key, -1);
if (value == -1) continue;
if (value == -1) {
continue;
}
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInitF(&brightness->name, "acpiout%d", i);
@@ -1,6 +1,5 @@
#include "brightness.h"
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result)
{
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result) {
return "Not supported on this platform";
}
+7 -5
View File
@@ -6,8 +6,7 @@
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) {
char path[] = "/dev/ttyCX";
for (char i = '0'; i <= '9'; ++i) {
path[strlen("/dev/ttyC")] = i;
@@ -15,10 +14,12 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
FF_AUTO_CLOSE_FD int devfd = open(path, O_RDONLY | O_CLOEXEC);
if (devfd < 0) {
if (errno == EACCES && i == '0')
if (errno == EACCES && i == '0') {
return "Permission denied when opening tty device";
if (errno == ENOENT)
}
if (errno == ENOENT) {
break;
}
continue;
}
@@ -26,8 +27,9 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
.param = WSDISPLAYIO_PARAM_BRIGHTNESS,
};
if (ioctl(devfd, WSDISPLAYIO_GETPARAM, &param) < 0)
if (ioctl(devfd, WSDISPLAYIO_GETPARAM, &param) < 0) {
continue;
}
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInitF(&brightness->name, "ttyC%c", i);
+52 -59
View File
@@ -1,5 +1,4 @@
extern "C"
{
extern "C" {
#include "brightness.h"
#include "detection/displayserver/displayserver.h"
#include "common/library.h"
@@ -10,45 +9,40 @@ extern "C"
#include <winternl.h>
NTSYSAPI NTSTATUS WINAPI GetPhysicalMonitors(
_In_ UNICODE_STRING *pstrDeviceName,
_In_ DWORD dwPhysicalMonitorArraySize,
_Out_ DWORD *pdwNumPhysicalMonitorHandlesInArray,
_Out_ HANDLE *phPhysicalMonitorArray
);
_In_ UNICODE_STRING* pstrDeviceName,
_In_ DWORD dwPhysicalMonitorArraySize,
_Out_ DWORD* pdwNumPhysicalMonitorHandlesInArray,
_Out_ HANDLE* phPhysicalMonitorArray);
typedef enum _MC_VCP_CODE_TYPE {
MC_MOMENTARY,
MC_SET_PARAMETER
} MC_VCP_CODE_TYPE, *LPMC_VCP_CODE_TYPE;
MC_MOMENTARY,
MC_SET_PARAMETER
} MC_VCP_CODE_TYPE,
*LPMC_VCP_CODE_TYPE;
NTSYSAPI NTSTATUS WINAPI DDCCIGetVCPFeature(
_In_ HANDLE hMonitor,
_In_ DWORD dwVCPCode,
_Out_opt_ LPMC_VCP_CODE_TYPE pvct,
_Out_ DWORD *pdwCurrentValue,
_Out_opt_ DWORD *pdwMaximumValue
);
_In_ HANDLE hMonitor,
_In_ DWORD dwVCPCode,
_Out_opt_ LPMC_VCP_CODE_TYPE pvct,
_Out_ DWORD* pdwCurrentValue,
_Out_opt_ DWORD* pdwMaximumValue);
NTSYSAPI NTSTATUS WINAPI DestroyPhysicalMonitorInternal(
_In_ HANDLE hMonitor
);
_In_ HANDLE hMonitor);
NTSTATUS WINAPI GetPhysicalMonitorDescription(
_In_ HANDLE hMonitor,
_In_ DWORD dwPhysicalMonitorDescriptionSizeInChars,
_Out_ LPWSTR szPhysicalMonitorDescription
);
_In_ HANDLE hMonitor,
_In_ DWORD dwPhysicalMonitorDescriptionSizeInChars,
_Out_ LPWSTR szPhysicalMonitorDescription);
static const char* detectWithWmi(FFlist* result)
{
static const char* detectWithWmi(FFlist* result) {
FFWmiQuery query(L"SELECT CurrentBrightness, InstanceName FROM WmiMonitorBrightness WHERE Active = true", nullptr, FFWmiNamespace::WMI);
if(!query)
if (!query) {
return "Query WMI service failed";
}
while(FFWmiRecord record = query.next())
{
if(FFWmiVariant vtValue = record.get(L"CurrentBrightness"))
{
while (FFWmiRecord record = query.next()) {
if (FFWmiVariant vtValue = record.get(L"CurrentBrightness")) {
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->max = 100;
brightness->min = 0;
@@ -56,8 +50,7 @@ static const char* detectWithWmi(FFlist* result)
brightness->builtin = true;
ffStrbufInit(&brightness->name);
if (FFWmiVariant vtName = record.get(L"InstanceName"))
{
if (FFWmiVariant vtName = record.get(L"InstanceName")) {
ffStrbufSetWSV(&brightness->name, vtName.get<std::wstring_view>());
ffStrbufSubstrAfterFirstC(&brightness->name, '\\');
ffStrbufSubstrBeforeFirstC(&brightness->name, '\\');
@@ -67,22 +60,25 @@ static const char* detectWithWmi(FFlist* result)
return NULL;
}
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result)
{
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result) {
void* gdi32 = ffLibraryGetModule(L"gdi32.dll");
if (!gdi32) return "ffLibraryGetModule(gdi32.dll) failed";
if (!gdi32) {
return "ffLibraryGetModule(gdi32.dll) failed";
}
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, GetPhysicalMonitors)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DDCCIGetVCPFeature)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DestroyPhysicalMonitorInternal)
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_BUILTIN) continue;
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
if (display->type == FF_DISPLAY_TYPE_BUILTIN) {
continue;
}
MONITORINFOEXW mi;
mi.cbSize = sizeof(mi);
if (!GetMonitorInfoW((HMONITOR)(uintptr_t) display->id, (LPMONITORINFO) &mi))
if (!GetMonitorInfoW((HMONITOR) (uintptr_t) display->id, (LPMONITORINFO) &mi)) {
continue;
}
UNICODE_STRING deviceName = {
.Length = (USHORT) (wcslen(mi.szDevice) * sizeof(wchar_t)),
@@ -91,25 +87,23 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
};
HANDLE physicalMonitor;
DWORD monitorCount = 0;
if (NT_SUCCESS(ffGetPhysicalMonitors(&deviceName, 1, &monitorCount, &physicalMonitor)) && monitorCount >= 1)
{
if (NT_SUCCESS(ffGetPhysicalMonitors(&deviceName, 1, &monitorCount, &physicalMonitor)) && monitorCount >= 1) {
DWORD curr = 0, max = 0;
if (NT_SUCCESS(ffDDCCIGetVCPFeature(physicalMonitor, 0x10 /* luminance */, NULL, &curr, &max)))
{
if (NT_SUCCESS(ffDDCCIGetVCPFeature(physicalMonitor, 0x10 /* luminance */, NULL, &curr, &max))) {
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
if (display->name.length > 0)
if (display->name.length > 0) {
ffStrbufInitCopy(&brightness->name, &display->name);
else
{
} else {
FF_LIBRARY_LOAD_SYMBOL_LAZY(gdi32, GetPhysicalMonitorDescription)
if (ffGetPhysicalMonitorDescription)
{
if (ffGetPhysicalMonitorDescription) {
wchar_t description[128 /*MUST be PHYSICAL_MONITOR_DESCRIPTION_SIZE*/];
if (NT_SUCCESS(ffGetPhysicalMonitorDescription(physicalMonitor, ARRAY_SIZE(description), description)))
if (NT_SUCCESS(ffGetPhysicalMonitorDescription(physicalMonitor, ARRAY_SIZE(description), description))) {
ffStrbufInitWS(&brightness->name, description);
}
}
if (brightness->name.length == 0)
if (brightness->name.length == 0) {
ffStrbufSetNWS(&brightness->name, deviceName.Length / 2, deviceName.Buffer);
}
}
brightness->max = max;
brightness->min = 0;
@@ -123,25 +117,24 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
return NULL;
}
static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer)
{
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN)
static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer) {
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN) {
return true;
}
}
return false;
}
extern "C"
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
extern "C" const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) {
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
if (hasBuiltinDisplay(displayServer))
if (hasBuiltinDisplay(displayServer)) {
detectWithWmi(result);
}
if (result->length < displayServer->displays.length)
if (result->length < displayServer->displays.length) {
detectWithDdcci(displayServer, result);
}
return NULL;
}
+2 -4
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/btrfs/option.h"
typedef struct FFBtrfsDiskUsage
{
typedef struct FFBtrfsDiskUsage {
uint64_t total;
uint64_t used;
const char* type;
@@ -12,8 +11,7 @@ typedef struct FFBtrfsDiskUsage
uint8_t copies;
} FFBtrfsDiskUsage;
typedef struct FFBtrfsResult
{
typedef struct FFBtrfsResult {
FFstrbuf name;
FFstrbuf uuid;
FFstrbuf devices;
+80 -65
View File
@@ -5,132 +5,141 @@
enum { uuidLen = (uint32_t) __builtin_strlen("00000000-0000-0000-0000-000000000000") };
static const char* enumerateDevices(FFBtrfsResult* item, int dfd, FFstrbuf* buffer)
{
static const char* enumerateDevices(FFBtrfsResult* item, int dfd, FFstrbuf* buffer) {
int subfd = openat(dfd, "devices", O_RDONLY | O_CLOEXEC | O_DIRECTORY);
if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/devices\") == -1";
if (subfd < 0) {
return "openat(\"/sys/fs/btrfs/UUID/devices\") == -1";
}
FF_AUTO_CLOSE_DIR DIR* dirp = fdopendir(subfd);
if(dirp == NULL)
{
if (dirp == NULL) {
close(subfd);
return "fdopendir(\"/sys/fs/btrfs/UUID/devices\") == NULL";
}
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
if (item->devices.length)
if (item->devices.length) {
ffStrbufAppendC(&item->devices, ',');
}
ffStrbufAppendS(&item->devices, entry->d_name);
char path[sizeof(entry->d_name) + sizeof("/size") + 1];
snprintf(path, ARRAY_SIZE(path), "%s/size", entry->d_name);
if (ffReadFileBufferRelative(subfd, path, buffer))
if (ffReadFileBufferRelative(subfd, path, buffer)) {
item->totalSize += ffStrbufToUInt(buffer, 0) * 512;
}
}
return NULL;
}
static const char* enumerateFeatures(FFBtrfsResult* item, int dfd)
{
static const char* enumerateFeatures(FFBtrfsResult* item, int dfd) {
int subfd = openat(dfd, "features", O_RDONLY | O_CLOEXEC | O_DIRECTORY);
if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/features\") == -1";
if (subfd < 0) {
return "openat(\"/sys/fs/btrfs/UUID/features\") == -1";
}
FF_AUTO_CLOSE_DIR DIR* dirp = fdopendir(subfd);
if(dirp == NULL)
if (dirp == NULL) {
return "fdopendir(\"/sys/fs/btrfs/UUID/features\") == NULL";
}
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
if (item->features.length)
}
if (item->features.length) {
ffStrbufAppendC(&item->features, ',');
}
ffStrbufAppendS(&item->features, entry->d_name);
}
return NULL;
}
static const char* detectAllocation(FFBtrfsResult* item, int dfd, FFstrbuf* buffer)
{
static const char* detectAllocation(FFBtrfsResult* item, int dfd, FFstrbuf* buffer) {
FF_AUTO_CLOSE_FD int subfd = openat(dfd, "allocation", O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/allocation\") == -1";
if (subfd < 0) {
return "openat(\"/sys/fs/btrfs/UUID/allocation\") == -1";
}
if (ffReadFileBufferRelative(subfd, "global_rsv_size", buffer))
if (ffReadFileBufferRelative(subfd, "global_rsv_size", buffer)) {
item->globalReservationTotal = ffStrbufToUInt(buffer, 0);
else
} else {
return "ffReadFileBuffer(\"/sys/fs/btrfs/UUID/allocation/global_rsv_size\") == NULL";
}
if (ffReadFileBufferRelative(subfd, "global_rsv_reserved", buffer))
if (ffReadFileBufferRelative(subfd, "global_rsv_reserved", buffer)) {
item->globalReservationUsed = ffStrbufToUInt(buffer, 0);
}
item->globalReservationUsed = item->globalReservationTotal - item->globalReservationUsed;
#define FF_BTRFS_DETECT_PROFILE(_index, _type, _profile, _copies) \
else if (faccessat(subfd, _type "/" _profile "/", F_OK, 0) == 0) { \
item->allocation[_index].profile = _profile; \
item->allocation[_index].copies = _copies; \
}
#define FF_BTRFS_DETECT_PROFILE(_index, _type, _profile, _copies) \
else if (faccessat(subfd, _type "/" _profile "/", F_OK, 0) == 0) { \
item->allocation[_index].profile = _profile; \
item->allocation[_index].copies = _copies; \
}
#define FF_BTRFS_DETECT_TYPE(_index, _type) \
do { \
item->allocation[_index].type = _type; \
#define FF_BTRFS_DETECT_TYPE(_index, _type) \
do { \
item->allocation[_index].type = _type; \
if (ffReadFileBufferRelative(subfd, _type "/total_bytes", buffer)) \
item->allocation[_index].total = ffStrbufToUInt(buffer, 0); \
\
if (ffReadFileBufferRelative(subfd, _type "/bytes_used", buffer)) \
item->allocation[_index].used = ffStrbufToUInt(buffer, 0); \
\
if (false) {} \
FF_BTRFS_DETECT_PROFILE(_index, _type, "single", 1) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "dup", 2) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid0", 1) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1", 2) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid10", 2) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c3", 3) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c4", 4) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid5", 1) /* (n-1)/n */ \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid6", 1) /* (n-2)/n */ \
else { \
item->allocation[_index].profile = "unknown"; \
item->allocation[_index].copies = 1; \
} \
item->allocation[_index].total = ffStrbufToUInt(buffer, 0); \
\
if (ffReadFileBufferRelative(subfd, _type "/bytes_used", buffer)) \
item->allocation[_index].used = ffStrbufToUInt(buffer, 0); \
\
if (false) {} \
FF_BTRFS_DETECT_PROFILE(_index, _type, "single", 1) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "dup", 2) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid0", 1) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1", 2) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid10", 2) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c3", 3) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c4", 4) \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid5", 1) /* (n-1)/n */ \
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid6", 1) /* (n-2)/n */ \
else { \
item->allocation[_index].profile = "unknown"; \
item->allocation[_index].copies = 1; \
} \
} while (0)
FF_BTRFS_DETECT_TYPE(0, "data");
FF_BTRFS_DETECT_TYPE(1, "metadata");
FF_BTRFS_DETECT_TYPE(2, "system");
#undef FF_BTRFS_DETECT_TYPE
#undef FF_BTRFS_DETECT_TYPE
return NULL;
}
const char* ffDetectBtrfs(FFlist* result)
{
const char* ffDetectBtrfs(FFlist* result) {
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/fs/btrfs/");
if(dirp == NULL)
if (dirp == NULL) {
return "opendir(\"/sys/fs/btrfs\") == NULL";
}
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
if (strlen(entry->d_name) != uuidLen)
}
if (strlen(entry->d_name) != uuidLen) {
continue;
}
FFBtrfsResult* item = ffListAdd(result);
(*item) = (FFBtrfsResult){
(*item) = (FFBtrfsResult) {
.uuid = ffStrbufCreateNS(uuidLen, entry->d_name),
.name = ffStrbufCreate(),
.devices = ffStrbufCreate(),
@@ -138,23 +147,29 @@ const char* ffDetectBtrfs(FFlist* result)
};
FF_AUTO_CLOSE_FD int dfd = openat(dirfd(dirp), entry->d_name, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
if (dfd < 0) continue;
if (dfd < 0) {
continue;
}
if (ffAppendFileBufferRelative(dfd, "label", &item->name))
if (ffAppendFileBufferRelative(dfd, "label", &item->name)) {
ffStrbufTrimRightSpace(&item->name);
}
enumerateDevices(item, dfd, &buffer);
enumerateFeatures(item, dfd);
if (ffReadFileBufferRelative(dfd, "generation", &buffer))
if (ffReadFileBufferRelative(dfd, "generation", &buffer)) {
item->generation = (uint32_t) ffStrbufToUInt(&buffer, 0);
}
if (ffReadFileBufferRelative(dfd, "nodesize", &buffer))
if (ffReadFileBufferRelative(dfd, "nodesize", &buffer)) {
item->nodeSize = (uint32_t) ffStrbufToUInt(&buffer, 0);
}
if (ffReadFileBufferRelative(dfd, "sectorsize", &buffer))
if (ffReadFileBufferRelative(dfd, "sectorsize", &buffer)) {
item->sectorSize = (uint32_t) ffStrbufToUInt(&buffer, 0);
}
detectAllocation(item, dfd, &buffer);
}
+1 -2
View File
@@ -1,6 +1,5 @@
#include "btrfs.h"
const char* ffDetectBtrfs(FF_MAYBE_UNUSED FFlist* result)
{
const char* ffDetectBtrfs(FF_MAYBE_UNUSED FFlist* result) {
return "Not supported on this platform";
}
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/camera/option.h"
typedef struct FFCameraResult
{
typedef struct FFCameraResult {
FFstrbuf name;
FFstrbuf vendor;
FFstrbuf id;
+17 -20
View File
@@ -6,54 +6,51 @@
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
#define FF_TERMUX_API_PARAM "CameraInfo"
static inline void wrapYyjsonFree(yyjson_doc** doc)
{
static inline void wrapYyjsonFree(yyjson_doc** doc) {
assert(doc);
if (*doc)
if (*doc) {
yyjson_doc_free(*doc);
}
}
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
{
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if(ffProcessAppendStdOut(&buffer, (char* const[]){
FF_TERMUX_API_PATH,
FF_TERMUX_API_PARAM,
NULL
}))
if (ffProcessAppendStdOut(&buffer, (char* const[]) {FF_TERMUX_API_PATH, FF_TERMUX_API_PARAM, NULL})) {
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
}
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(buffer.chars, buffer.length, 0, NULL, NULL);
if (!doc)
if (!doc) {
return "Failed to parse camera info";
}
yyjson_val* root = yyjson_doc_get_root(doc);
if (!yyjson_is_arr(root))
if (!yyjson_is_arr(root)) {
return "Camera info result is not a JSON array";
}
yyjson_val* device;
size_t idx, max;
yyjson_arr_foreach(root, idx, max, device)
{
yyjson_arr_foreach (root, idx, max, device) {
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
{
const char* facing = yyjson_get_str(yyjson_obj_get(device, "facing"));
if (facing)
if (facing) {
ffStrbufInitF(&camera->name, "builtin-%s", facing);
else
} else {
ffStrbufInitStatic(&camera->name, "Unknown");
}
}
ffStrbufInit(&camera->vendor);
ffStrbufInitJsonVal(&camera->id, yyjson_obj_get(device, "id"));
yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes"));
if (yyjson_is_obj(sizes))
{
if (yyjson_is_obj(sizes)) {
camera->width = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "width"));
camera->height = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "height"));
}
else
} else {
camera->width = camera->height = 0;
}
ffStrbufInit(&camera->colorspace);
}
+53 -29
View File
@@ -6,57 +6,81 @@
#include <sys/ioctl.h>
#if FF_HAVE_LINUX_VIDEODEV2
#include <linux/videodev2.h>
# include <linux/videodev2.h>
#elif __has_include(<sys/videoio.h>) // OpenBSD
#include <sys/videoio.h>
#define FF_HAVE_LINUX_VIDEODEV2 1
# include <sys/videoio.h>
# define FF_HAVE_LINUX_VIDEODEV2 1
#endif
const char* ffDetectCamera(FFlist* result)
{
const char* ffDetectCamera(FFlist* result) {
#if FF_HAVE_LINUX_VIDEODEV2
char path[] = "/dev/videoN";
for (uint32_t i = 0; i <= 9; ++i)
{
for (uint32_t i = 0; i <= 9; ++i) {
path[ARRAY_SIZE(path) - 2] = (char) (i + '0');
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0)
{
if (errno == ENOENT)
if (fd < 0) {
if (errno == ENOENT) {
break;
if (errno == ENXIO)
}
if (errno == ENXIO) {
continue;
}
return "Failed to open /dev/videoN";
}
struct v4l2_capability cap = {};
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
continue;
}
struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
struct v4l2_format fmt = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) {
continue;
}
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitS(&camera->name, (const char*) cap.card);
ffStrbufInit(&camera->vendor);
ffStrbufInitS(&camera->id, (const char*) cap.bus_info);
switch (fmt.fmt.pix.colorspace)
{
case V4L2_COLORSPACE_SMPTE170M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M"); break;
case V4L2_COLORSPACE_SMPTE240M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M"); break;
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.878"); break;
case V4L2_COLORSPACE_470_SYSTEM_M: ffStrbufInitStatic(&camera->colorspace, "NTSC"); break;
case V4L2_COLORSPACE_470_SYSTEM_BG: ffStrbufInitStatic(&camera->colorspace, "EBU 3213"); break;
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
case V4L2_COLORSPACE_REC709:
case V4L2_COLORSPACE_SRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
case 9 /* V4L2_COLORSPACE_OPRGB */: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
case 10 /* V4L2_COLORSPACE_BT2020 */: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
case 11 /* V4L2_COLORSPACE_RAW */: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
case 12 /* V4L2_COLORSPACE_DCI_P3 */: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
default: ffStrbufInit(&camera->colorspace); break;
switch (fmt.fmt.pix.colorspace) {
case V4L2_COLORSPACE_SMPTE170M:
ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M");
break;
case V4L2_COLORSPACE_SMPTE240M:
ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M");
break;
case V4L2_COLORSPACE_BT878:
ffStrbufInitStatic(&camera->colorspace, "BT.878");
break;
case V4L2_COLORSPACE_470_SYSTEM_M:
ffStrbufInitStatic(&camera->colorspace, "NTSC");
break;
case V4L2_COLORSPACE_470_SYSTEM_BG:
ffStrbufInitStatic(&camera->colorspace, "EBU 3213");
break;
case V4L2_COLORSPACE_JPEG:
ffStrbufInitStatic(&camera->colorspace, "JPEG");
break;
case V4L2_COLORSPACE_REC709:
case V4L2_COLORSPACE_SRGB:
ffStrbufInitStatic(&camera->colorspace, "sRGB");
break;
case 9 /* V4L2_COLORSPACE_OPRGB */:
ffStrbufInitStatic(&camera->colorspace, "Adobe RGB");
break;
case 10 /* V4L2_COLORSPACE_BT2020 */:
ffStrbufInitStatic(&camera->colorspace, "BT.2020");
break;
case 11 /* V4L2_COLORSPACE_RAW */:
ffStrbufInitStatic(&camera->colorspace, "RAW");
break;
case 12 /* V4L2_COLORSPACE_DCI_P3 */:
ffStrbufInitStatic(&camera->colorspace, "DCI-P3");
break;
default:
ffStrbufInit(&camera->colorspace);
break;
}
camera->width = fmt.fmt.pix.width;
camera->height = fmt.fmt.pix.height;
+1 -2
View File
@@ -1,6 +1,5 @@
#include "camera.h"
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
{
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result) {
return "Not support on this platform";
}
+66 -38
View File
@@ -10,42 +10,43 @@ extern "C" {
#include <mfapi.h>
#include <mfidl.h>
extern "C"
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
{
extern "C" const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(mfplat, "mfplat" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
FF_LIBRARY_LOAD_MESSAGE(mf, "mf" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mf, MFEnumDeviceSources)
const char* error = ffInitCom();
if (error)
if (error) {
return error;
}
IMFAttributes* FF_AUTO_RELEASE_COM_OBJECT attrs = nullptr;
if (FAILED(ffMFCreateAttributes(&attrs, 1)))
if (FAILED(ffMFCreateAttributes(&attrs, 1))) {
return "MFCreateAttributes() failed";
}
if (FAILED(attrs->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
)))
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID))) {
return "SetGUID(MF_*) failed";
}
IMFActivate** devices = NULL;
uint32_t count;
if (FAILED(ffMFEnumDeviceSources(attrs, &devices, &count)))
if (FAILED(ffMFEnumDeviceSources(attrs, &devices, &count))) {
return "MFEnumDeviceSources() failed";
}
for (uint32_t i = 0; i < count; i++)
{
for (uint32_t i = 0; i < count; i++) {
IMFActivate* FF_AUTO_RELEASE_COM_OBJECT device = devices[i];
wchar_t buffer[256];
uint32_t length = 0;
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, ARRAY_SIZE(buffer), &length)) || length == 0)
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, ARRAY_SIZE(buffer), &length)) || length == 0) {
continue;
}
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitNWS(&camera->name, length, buffer);
@@ -55,60 +56,85 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
camera->width = 0;
camera->height = 0;
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, ARRAY_SIZE(buffer), &length)) && length > 0)
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, ARRAY_SIZE(buffer), &length)) && length > 0) {
ffStrbufSetNWS(&camera->id, length, buffer);
}
IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr;
if (FAILED(device->ActivateObject(IID_PPV_ARGS(&source))))
if (FAILED(device->ActivateObject(IID_PPV_ARGS(&source)))) {
continue;
}
on_scope_exit destroySource([&] { source->Shutdown(); });
IMFPresentationDescriptor* FF_AUTO_RELEASE_COM_OBJECT pd = nullptr;
if (FAILED(source->CreatePresentationDescriptor(&pd)))
if (FAILED(source->CreatePresentationDescriptor(&pd))) {
continue;
}
IMFStreamDescriptor* FF_AUTO_RELEASE_COM_OBJECT sd = NULL;
BOOL selected;
if (FAILED(pd->GetStreamDescriptorByIndex(0, &selected, &sd)))
if (FAILED(pd->GetStreamDescriptorByIndex(0, &selected, &sd))) {
continue;
}
IMFMediaTypeHandler* FF_AUTO_RELEASE_COM_OBJECT handler = NULL;
if (FAILED(sd->GetMediaTypeHandler(&handler)))
if (FAILED(sd->GetMediaTypeHandler(&handler))) {
continue;
}
DWORD mediaTypeCount;
if (FAILED(handler->GetMediaTypeCount(&mediaTypeCount)))
if (FAILED(handler->GetMediaTypeCount(&mediaTypeCount))) {
continue;
}
// Assume first type is the maximum resolution
IMFMediaType* type = NULL;
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx)
{
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx) {
on_scope_exit destroyType([=] { type->Release(); });
GUID majorType;
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video)
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video) {
continue;
}
MFVideoPrimaries primaries;
static_assert(sizeof(primaries) == sizeof(uint32_t), "");
if (SUCCEEDED(type->GetUINT32(MF_MT_VIDEO_PRIMARIES, (uint32_t*) &primaries)))
{
switch (primaries)
{
case MFVideoPrimaries_BT709: ffStrbufSetStatic(&camera->colorspace, "sRGB"); break;
case MFVideoPrimaries_BT470_2_SysM:
case MFVideoPrimaries_BT470_2_SysBG: ffStrbufSetStatic(&camera->colorspace, "NTSC"); break;
case MFVideoPrimaries_SMPTE170M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 170M"); break;
case MFVideoPrimaries_SMPTE240M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 240M"); break;
case MFVideoPrimaries_EBU3213: ffStrbufSetStatic(&camera->colorspace, "EBU 3213"); break;
case MFVideoPrimaries_SMPTE_C: ffStrbufSetStatic(&camera->colorspace, "SMPTE C"); break;
case MFVideoPrimaries_BT2020: ffStrbufSetStatic(&camera->colorspace, "BT.2020"); break;
case MFVideoPrimaries_XYZ: ffStrbufSetStatic(&camera->colorspace, "XYZ"); break;
case MFVideoPrimaries_DCI_P3: ffStrbufSetStatic(&camera->colorspace, "DCI-P3"); break;
case MFVideoPrimaries_ACES: ffStrbufSetStatic(&camera->colorspace, "ACES"); break;
default: break;
if (SUCCEEDED(type->GetUINT32(MF_MT_VIDEO_PRIMARIES, (uint32_t*) &primaries))) {
switch (primaries) {
case MFVideoPrimaries_BT709:
ffStrbufSetStatic(&camera->colorspace, "sRGB");
break;
case MFVideoPrimaries_BT470_2_SysM:
case MFVideoPrimaries_BT470_2_SysBG:
ffStrbufSetStatic(&camera->colorspace, "NTSC");
break;
case MFVideoPrimaries_SMPTE170M:
ffStrbufSetStatic(&camera->colorspace, "SMPTE 170M");
break;
case MFVideoPrimaries_SMPTE240M:
ffStrbufSetStatic(&camera->colorspace, "SMPTE 240M");
break;
case MFVideoPrimaries_EBU3213:
ffStrbufSetStatic(&camera->colorspace, "EBU 3213");
break;
case MFVideoPrimaries_SMPTE_C:
ffStrbufSetStatic(&camera->colorspace, "SMPTE C");
break;
case MFVideoPrimaries_BT2020:
ffStrbufSetStatic(&camera->colorspace, "BT.2020");
break;
case MFVideoPrimaries_XYZ:
ffStrbufSetStatic(&camera->colorspace, "XYZ");
break;
case MFVideoPrimaries_DCI_P3:
ffStrbufSetStatic(&camera->colorspace, "DCI-P3");
break;
case MFVideoPrimaries_ACES:
ffStrbufSetStatic(&camera->colorspace, "ACES");
break;
default:
break;
}
}
@@ -117,7 +143,9 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
}
}
if (devices) CoTaskMemFree(devices);
if (devices) {
CoTaskMemFree(devices);
}
return nullptr;
}
+76 -41
View File
@@ -1,47 +1,82 @@
#include "chassis.h"
const char* ffChassisTypeToString(uint32_t type)
{
const char* ffChassisTypeToString(uint32_t type) {
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.7.0.pdf
// 7.4.1 System Enclosure or Chassis Types
switch (type & 0b01111111)
{
case 0x01: return "Other";
case 0x02: return "Unknown";
case 0x03: return "Desktop";
case 0x04: return "Low Profile Desktop";
case 0x05: return "Pizza Box";
case 0x06: return "Mini Tower";
case 0x07: return "Tower";
case 0x08: return "Portable";
case 0x09: return "Laptop";
case 0x0A: return "Notebook";
case 0x0B: return "Hand Held";
case 0x0C: return "Docking Station";
case 0x0D: return "All in One";
case 0x0E: return "Sub Notebook";
case 0x0F: return "Space-saving";
case 0x10: return "Lunch Box";
case 0x11: return "Main Server Chassis";
case 0x12: return "Expansion Chassis";
case 0x13: return "SubChassis";
case 0x14: return "Bus Expansion Chassis";
case 0x15: return "Peripheral Chassis";
case 0x16: return "RAID Chassis";
case 0x17: return "Rack Mount Chassis";
case 0x18: return "Sealed-case PC";
case 0x19: return "Multi-system chassis";
case 0x1A: return "Compact PCI";
case 0x1B: return "Advanced TCA";
case 0x1C: return "Blade";
case 0x1D: return "Mobile Workstation";
case 0x1E: return "Tablet";
case 0x1F: return "Convertible";
case 0x20: return "Detachable";
case 0x21: return "IoT Gateway";
case 0x22: return "Embedded PC";
case 0x23: return "Mini PC";
case 0x24: return "Stick PC";
default: return NULL;
switch (type & 0b01111111) {
case 0x01:
return "Other";
case 0x02:
return "Unknown";
case 0x03:
return "Desktop";
case 0x04:
return "Low Profile Desktop";
case 0x05:
return "Pizza Box";
case 0x06:
return "Mini Tower";
case 0x07:
return "Tower";
case 0x08:
return "Portable";
case 0x09:
return "Laptop";
case 0x0A:
return "Notebook";
case 0x0B:
return "Hand Held";
case 0x0C:
return "Docking Station";
case 0x0D:
return "All in One";
case 0x0E:
return "Sub Notebook";
case 0x0F:
return "Space-saving";
case 0x10:
return "Lunch Box";
case 0x11:
return "Main Server Chassis";
case 0x12:
return "Expansion Chassis";
case 0x13:
return "SubChassis";
case 0x14:
return "Bus Expansion Chassis";
case 0x15:
return "Peripheral Chassis";
case 0x16:
return "RAID Chassis";
case 0x17:
return "Rack Mount Chassis";
case 0x18:
return "Sealed-case PC";
case 0x19:
return "Multi-system chassis";
case 0x1A:
return "Compact PCI";
case 0x1B:
return "Advanced TCA";
case 0x1C:
return "Blade";
case 0x1D:
return "Mobile Workstation";
case 0x1E:
return "Tablet";
case 0x1F:
return "Convertible";
case 0x20:
return "Detachable";
case 0x21:
return "IoT Gateway";
case 0x22:
return "Embedded PC";
case 0x23:
return "Mini PC";
case 0x24:
return "Stick PC";
default:
return NULL;
}
}
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/chassis/option.h"
typedef struct FFChassisResult
{
typedef struct FFChassisResult {
FFstrbuf type;
FFstrbuf serial;
FFstrbuf vendor;
+9 -8
View File
@@ -1,8 +1,7 @@
#include "chassis.h"
#include "detection/host/host.h"
const char* ffDetectChassis(FFChassisResult* result)
{
const char* ffDetectChassis(FFChassisResult* result) {
FFHostResult host = {
.family = ffStrbufCreate(),
.name = ffStrbufCreate(),
@@ -12,18 +11,20 @@ const char* ffDetectChassis(FFChassisResult* result)
.uuid = ffStrbufCreate(),
.vendor = ffStrbufCreate(),
};
if (ffDetectHost(&host) != NULL)
if (ffDetectHost(&host) != NULL) {
return "Failed to detect host";
}
if (ffStrbufStartsWithS(&host.name, "MacBook "))
if (ffStrbufStartsWithS(&host.name, "MacBook ")) {
ffStrbufSetStatic(&result->type, "Laptop");
else if (ffStrbufStartsWithS(&host.name, "Mac mini ") ||
ffStrbufStartsWithS(&host.name, "Mac Studio "))
} else if (ffStrbufStartsWithS(&host.name, "Mac mini ") ||
ffStrbufStartsWithS(&host.name, "Mac Studio ")) {
ffStrbufSetStatic(&result->type, "Mini PC");
else if (ffStrbufStartsWithS(&host.name, "iMac "))
} else if (ffStrbufStartsWithS(&host.name, "iMac ")) {
ffStrbufSetStatic(&result->type, "All in One");
else
} else {
ffStrbufSetStatic(&result->type, "Desktop");
}
ffStrbufSet(&result->vendor, &host.vendor);
+1 -2
View File
@@ -2,8 +2,7 @@
#include "common/settings.h"
#include "common/smbiosHelper.h"
const char* ffDetectChassis(FFChassisResult* result)
{
const char* ffDetectChassis(FFChassisResult* result) {
// Unlike other platforms, `smbios.chassis.type` return display string directly on my machine
ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type);
ffCleanUpSmbiosValue(&result->type);
+11 -15
View File
@@ -4,37 +4,33 @@
#include <ctype.h>
const char* ffDetectChassis(FFChassisResult* result)
{
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type))
{
const char* ffDetectChassis(FFChassisResult* result) {
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type)) {
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_serial", "/sys/class/dmi/id/chassis_serial", &result->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version);
if(result->type.length)
{
if (result->type.length) {
const char* typeStr = ffChassisTypeToString((uint32_t) ffStrbufToUInt(&result->type, 9999));
if(typeStr)
if (typeStr) {
ffStrbufSetStatic(&result->type, typeStr);
}
}
}
else
{
} else {
// Available on Asahi Linux
uint32_t chassisType = 0;
if (ffReadFileData("/sys/firmware/devicetree/base/smbios/smbios/chassis/chassis-type", sizeof(chassisType), &chassisType)) // big endian
{
chassisType = __builtin_bswap32(chassisType);
const char* typeStr = ffChassisTypeToString(chassisType);
if(typeStr)
if (typeStr) {
ffStrbufSetStatic(&result->type, typeStr);
}
if(ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/chassis/manufacturer", &result->vendor) && result->vendor.length > 0)
if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/chassis/manufacturer", &result->vendor) && result->vendor.length > 0) {
ffStrbufTrimRight(&result->vendor, '\0');
}
else if(ffReadFileBuffer("/sys/firmware/devicetree/base/chassis-type", &result->type) && result->type.length > 0)
{
}
} else if (ffReadFileBuffer("/sys/firmware/devicetree/base/chassis-type", &result->type) && result->type.length > 0) {
ffStrbufTrimRight(&result->type, '\0');
result->type.chars[0] = (char) toupper(result->type.chars[0]);
}
+9 -6
View File
@@ -2,16 +2,19 @@
#include "common/sysctl.h"
#include "common/smbiosHelper.h"
const char* ffDetectChassis(FFChassisResult* chassis)
{
if (ffSysctlGetString("machdep.dmi.chassis-type", &chassis->type) == NULL)
const char* ffDetectChassis(FFChassisResult* chassis) {
if (ffSysctlGetString("machdep.dmi.chassis-type", &chassis->type) == NULL) {
ffCleanUpSmbiosValue(&chassis->type);
if (ffSysctlGetString("machdep.dmi.chassis-version", &chassis->version) == NULL)
}
if (ffSysctlGetString("machdep.dmi.chassis-version", &chassis->version) == NULL) {
ffCleanUpSmbiosValue(&chassis->version);
if (ffSysctlGetString("machdep.dmi.chassis-vendor", &chassis->vendor) == NULL)
}
if (ffSysctlGetString("machdep.dmi.chassis-vendor", &chassis->vendor) == NULL) {
ffCleanUpSmbiosValue(&chassis->vendor);
if (ffSysctlGetString("machdep.dmi.chassis-serial", &chassis->serial) == NULL)
}
if (ffSysctlGetString("machdep.dmi.chassis-serial", &chassis->serial) == NULL) {
ffCleanUpSmbiosValue(&chassis->serial);
}
return NULL;
}
+1 -2
View File
@@ -1,6 +1,5 @@
#include "chassis.h"
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result)
{
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result) {
return "Not supported on this platform";
}
+17 -17
View File
@@ -2,43 +2,43 @@
#include "common/smbiosHelper.h"
// 7.4
typedef struct FFSmbiosSystemEnclosure
{
typedef struct FFSmbiosSystemEnclosure {
FFSmbiosHeader Header;
uint8_t Manufacturer; // string
uint8_t Type; // varies
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t Manufacturer; // string
uint8_t Type; // varies
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t AssetTagNumber; // string
// 2.1+
uint8_t BootupState; // enum
uint8_t BootupState; // enum
uint8_t PowerSupplyState; // enum
uint8_t ThermalState; // enum
uint8_t SecurityStatus; // enum
uint8_t ThermalState; // enum
uint8_t SecurityStatus; // enum
// 2.3+
uint32_t OEMDefined; // varies
uint8_t Height; // varies
uint8_t NumberOfPowerCords; // varies
uint32_t OEMDefined; // varies
uint8_t Height; // varies
uint8_t NumberOfPowerCords; // varies
uint8_t ContainedElementCount; // varies
uint8_t ContainedRecordLength; // varies
uint8_t ContainedElements[]; // varies
uint8_t ContainedElements[]; // varies
} __attribute__((__packed__)) FFSmbiosSystemEnclosure;
static_assert(offsetof(FFSmbiosSystemEnclosure, ContainedElements) == 0x15,
"FFSmbiosSystemEnclosure: Wrong struct alignment");
const char* ffDetectChassis(FFChassisResult* result)
{
const char* ffDetectChassis(FFChassisResult* result) {
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
if (!smbiosTable)
if (!smbiosTable) {
return "Failed to get SMBIOS data";
}
const FFSmbiosSystemEnclosure* data = (const FFSmbiosSystemEnclosure*) (*smbiosTable)[FF_SMBIOS_TYPE_SYSTEM_ENCLOSURE];
if (!data)
if (!data) {
return "System enclosure is not found in SMBIOS data";
}
const char* strings = (const char*) data + data->Header.Length;
+24 -24
View File
@@ -2,8 +2,7 @@
#include "common/processing.h"
#include "common/FFstrbuf.h"
typedef struct FFCommandResultBundle
{
typedef struct FFCommandResultBundle {
FFProcessHandle handle;
const char* error;
} FFCommandResultBundle;
@@ -13,26 +12,25 @@ static FFlist commandQueue = {
.elementSize = sizeof(FFCommandResultBundle),
};
static const char* spawnProcess(FFCommandOptions* options, FFProcessHandle* handle)
{
if (options->text.length == 0)
static const char* spawnProcess(FFCommandOptions* options, FFProcessHandle* handle) {
if (options->text.length == 0) {
return "No command text specified";
}
return ffProcessSpawn(options->param.length ? (char* const[]){
options->shell.chars,
options->param.chars,
options->text.chars,
NULL
} : (char* const[]){
options->shell.chars,
options->text.chars,
NULL
}, options->useStdErr, handle);
return ffProcessSpawn(options->param.length ? (char* const[]) {
options->shell.chars,
options->param.chars,
options->text.chars,
NULL}
: (char* const[]) {options->shell.chars, options->text.chars, NULL},
options->useStdErr,
handle);
}
bool ffPrepareCommand(FFCommandOptions* options)
{
if (!options->parallel) return false;
bool ffPrepareCommand(FFCommandOptions* options) {
if (!options->parallel) {
return false;
}
FFCommandResultBundle* bundle = ffListAdd(&commandQueue);
bundle->error = spawnProcess(options, &bundle->handle);
@@ -40,20 +38,22 @@ bool ffPrepareCommand(FFCommandOptions* options)
return true;
}
const char* ffDetectCommand(FFCommandOptions* options, FFstrbuf* result)
{
const char* ffDetectCommand(FFCommandOptions* options, FFstrbuf* result) {
FFCommandResultBundle bundle = {};
if (!options->parallel)
if (!options->parallel) {
bundle.error = spawnProcess(options, &bundle.handle);
else if (!ffListShift(&commandQueue, &bundle))
} else if (!ffListShift(&commandQueue, &bundle)) {
return "[BUG] command queue is empty";
}
if (bundle.error)
if (bundle.error) {
return bundle.error;
}
bundle.error = ffProcessReadOutput(&bundle.handle, result);
if (bundle.error)
if (bundle.error) {
return bundle.error;
}
ffStrbufTrimRightSpace(result);
return NULL;
+201 -188
View File
@@ -2,111 +2,126 @@
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu);
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu)
{
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu) {
const char* error = ffDetectCPUImpl(options, cpu);
if (error) return error;
if (error) {
return error;
}
const char* removeStrings[] = {
" CPU", " FPU", " APU", " Processor",
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core"
};
" CPU", " FPU", " APU", " Processor", " Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core", " 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core"};
ffStrbufRemoveStrings(&cpu->name, ARRAY_SIZE(removeStrings), removeStrings);
uint32_t radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " w/ Radeon "); // w/ Radeon 780M Graphics
if (radeonGraphics >= cpu->name.length)
if (radeonGraphics >= cpu->name.length) {
radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " with Radeon ");
if (radeonGraphics < cpu->name.length)
}
if (radeonGraphics < cpu->name.length) {
ffStrbufSubstrBefore(&cpu->name, radeonGraphics);
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
}
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); // Cut the speed output in the name as we append our own
ffStrbufTrimRight(&cpu->name, ' '); // If we removed the @ in previous step there was most likely a space before it
ffStrbufRemoveDupWhitespaces(&cpu->name);
return NULL;
}
const char* ffCPUAppleCodeToName(uint32_t code)
{
const char* ffCPUAppleCodeToName(uint32_t code) {
// https://github.com/AsahiLinux/docs/wiki/Codenames
switch (code)
{
case 8103: return "Apple M1";
case 6000: return "Apple M1 Pro";
case 6001: return "Apple M1 Max";
case 6002: return "Apple M1 Ultra";
case 8112: return "Apple M2";
case 6020: return "Apple M2 Pro";
case 6021: return "Apple M2 Max";
case 6022: return "Apple M2 Ultra";
case 8122: return "Apple M3";
case 6030: return "Apple M3 Pro";
switch (code) {
case 8103:
return "Apple M1";
case 6000:
return "Apple M1 Pro";
case 6001:
return "Apple M1 Max";
case 6002:
return "Apple M1 Ultra";
case 8112:
return "Apple M2";
case 6020:
return "Apple M2 Pro";
case 6021:
return "Apple M2 Max";
case 6022:
return "Apple M2 Ultra";
case 8122:
return "Apple M3";
case 6030:
return "Apple M3 Pro";
case 6031:
case 6034: return "Apple M3 Max";
case 8132: return "Apple M4";
case 6040: return "Apple M4 Pro";
case 6041: return "Apple M4 Max";
default: return NULL;
case 6034:
return "Apple M3 Max";
case 8132:
return "Apple M4";
case 6040:
return "Apple M4 Pro";
case 6041:
return "Apple M4 Max";
default:
return NULL;
}
}
const char* ffCPUQualcommCodeToName(uint32_t code)
{
const char* ffCPUQualcommCodeToName(uint32_t code) {
// https://github.com/AsahiLinux/docs/wiki/Codenames
switch (code)
{
case 7180: return "Qualcomm Snapdragon 7c";
case 7280: return "Qualcomm Snapdragon 7c+ Gen 3";
case 8180: return "Qualcomm Snapdragon 8cx Gen 2 5G";
case 8280: return "Qualcomm Snapdragon 8cx Gen 3";
default: return NULL;
switch (code) {
case 7180:
return "Qualcomm Snapdragon 7c";
case 7280:
return "Qualcomm Snapdragon 7c+ Gen 3";
case 8180:
return "Qualcomm Snapdragon 8cx Gen 2 5G";
case 8280:
return "Qualcomm Snapdragon 8cx Gen 3";
default:
return NULL;
}
}
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
# include <cpuid.h>
void ffCPUDetectByCpuid(FFCPUResult* cpu)
{
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
if (__get_cpuid(0x16, &eax, &ebx, &ecx, &edx))
{
if (__get_cpuid(0x16, &eax, &ebx, &ecx, &edx)) {
// WARNING: CPUID may report frequencies of efficient cores
// cpuid returns 0 MHz when hypervisor is enabled
if (eax) cpu->frequencyBase = eax;
if (ebx) cpu->frequencyMax = ebx;
if (eax) {
cpu->frequencyBase = eax;
}
if (ebx) {
cpu->frequencyMax = ebx;
}
}
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx))
{
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
// Feature tests (leaf1.ecx, leaf7.ebx)
bool sse2 = (ecx & bit_SSE2) != 0;
bool sse4_2 = (ecx & bit_SSE4_2) != 0;
bool pclmul = (ecx & bit_PCLMUL) != 0;
bool popcnt = (ecx & bit_POPCNT) != 0;
bool fma = (ecx & bit_FMA) != 0;
bool osxsave = (ecx & bit_OSXSAVE) != 0;
bool sse2 = (ecx & bit_SSE2) != 0;
bool sse4_2 = (ecx & bit_SSE4_2) != 0;
bool pclmul = (ecx & bit_PCLMUL) != 0;
bool popcnt = (ecx & bit_POPCNT) != 0;
bool fma = (ecx & bit_FMA) != 0;
bool osxsave = (ecx & bit_OSXSAVE) != 0;
unsigned int eax7 = 0, ebx7 = 0, ecx7 = 0, edx7 = 0;
__get_cpuid_count(7, 0, &eax7, &ebx7, &ecx7, &edx7);
bool avx2 = (ebx7 & bit_AVX2) != 0;
bool bmi2 = (ebx7 & bit_BMI2) != 0;
bool avx512f = (ebx7 & bit_AVX512F) != 0;
bool avx2 = (ebx7 & bit_AVX2) != 0;
bool bmi2 = (ebx7 & bit_BMI2) != 0;
bool avx512f = (ebx7 & bit_AVX512F) != 0;
bool avx512bw = (ebx7 & bit_AVX512BW) != 0;
bool avx512dq = (ebx7 & bit_AVX512DQ) != 0;
// OS support for AVX/AVX512: check XGETBV (requires OSXSAVE)
bool avx_os = false;
bool avx_os = false;
bool avx512_os = false;
if (osxsave)
{
if (osxsave) {
__asm__ __volatile__(
"xgetbv"
: "=a"(eax), "=d"(edx)
: "c"(0)
:
);
uint64_t xcr0 = ((uint64_t)edx << 32) | eax;
:);
uint64_t xcr0 = ((uint64_t) edx << 32) | eax;
// AVX requires XCR0[1:2] == 11b (XMM and YMM state)
avx_os = (xcr0 & 0x6ULL) == 0x6ULL;
@@ -115,10 +130,15 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
}
cpu->march = "unknown";
if (avx512f && avx512bw && avx512dq && avx512_os) cpu->march = "x86_64-v4";
else if (avx2 && fma && bmi2 && avx_os) cpu->march = "x86_64-v3";
else if (sse4_2 && popcnt && pclmul) cpu->march = "x86_64-v2";
else if (sse2) cpu->march = "x86_64-v1";
if (avx512f && avx512bw && avx512dq && avx512_os) {
cpu->march = "x86_64-v4";
} else if (avx2 && fma && bmi2 && avx_os) {
cpu->march = "x86_64-v3";
} else if (sse4_2 && popcnt && pclmul) {
cpu->march = "x86_64-v2";
} else if (sse2) {
cpu->march = "x86_64-v1";
}
}
}
@@ -129,33 +149,32 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
// https://en.wikipedia.org/wiki/AArch64#ARM-A_(application_architecture)
// Worth noting: Apple M1 is marked as ARMv8.5-A on Wikipedia, but it lacks BTI (mandatory in v8.5)
#ifdef __linux__
#include "common/io.h"
#include <elf.h>
# ifdef __linux__
# include "common/io.h"
# include <elf.h>
// #include <asm/hwcap.h>
void ffCPUDetectByCpuid(FFCPUResult* cpu)
{
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
char buf[PROC_FILE_BUFFSIZ];
ssize_t nRead = ffReadFileData("/proc/self/auxv", ARRAY_SIZE(buf), buf);
if (nRead < (ssize_t) sizeof(Elf64_auxv_t)) return;
if (nRead < (ssize_t) sizeof(Elf64_auxv_t)) {
return;
}
uint64_t hwcap = 0, hwcap2 = 0;
for (Elf64_auxv_t* auxv = (Elf64_auxv_t*)buf; (char*)auxv < buf + nRead; ++auxv)
{
if (auxv->a_type == AT_HWCAP)
{
for (Elf64_auxv_t* auxv = (Elf64_auxv_t*) buf; (char*) auxv < buf + nRead; ++auxv) {
if (auxv->a_type == AT_HWCAP) {
hwcap = auxv->a_un.a_val;
}
else if (auxv->a_type == AT_HWCAP2)
{
} else if (auxv->a_type == AT_HWCAP2) {
hwcap2 = auxv->a_un.a_val;
}
}
if (!hwcap) return;
if (!hwcap) {
return;
}
cpu->march = "unknown";
@@ -164,31 +183,31 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
bool has_asimd = (hwcap & (1 << 1) /* HWCAP_ASIMD */) != 0;
// ARMv8.1-A
bool has_atomics = (hwcap & (1 << 8) /* HWCAP_ATOMICS */) != 0; // optional from v8.0
bool has_crc32 = (hwcap & (1 << 7) /* HWCAP_CRC32 */) != 0; // optional from v8.0
bool has_atomics = (hwcap & (1 << 8) /* HWCAP_ATOMICS */) != 0; // optional from v8.0
bool has_crc32 = (hwcap & (1 << 7) /* HWCAP_CRC32 */) != 0; // optional from v8.0
bool has_asimdrdm = (hwcap & (1 << 12) /* HWCAP_ASIMDRDM */) != 0; // optional from v8.0
// ARMv8.2-A
bool has_fphp = (hwcap & (1 << 9) /* HWCAP_FPHP */) != 0; // optional
bool has_fphp = (hwcap & (1 << 9) /* HWCAP_FPHP */) != 0; // optional
bool has_dcpop = (hwcap & (1 << 16) /* HWCAP_DCPOP */) != 0; // DC CVAP, optional from v8.1
// ARMv8.3-A
bool has_paca = (hwcap & (1 << 30) /* HWCAP_PACA */) != 0; // optional from v8.2
bool has_paca = (hwcap & (1 << 30) /* HWCAP_PACA */) != 0; // optional from v8.2
bool has_lrcpc = (hwcap & (1 << 15) /* HWCAP_LRCPC */) != 0; // optional from v8.2
bool has_fcma = (hwcap & (1 << 14) /* HWCAP_FCMA */) != 0; // optional from v8.2
bool has_fcma = (hwcap & (1 << 14) /* HWCAP_FCMA */) != 0; // optional from v8.2
bool has_jscvt = (hwcap & (1 << 13) /* HWCAP_JSCVT */) != 0; // optional from v8.2
// ARMv8.4-A
bool has_dit = (hwcap & (1 << 24) /* HWCAP_DIT */) != 0; // optional from v8.3
bool has_flagm = (hwcap & (1 << 27) /* HWCAP_FLAGM */) != 0; // optional from v8.1
bool has_dit = (hwcap & (1 << 24) /* HWCAP_DIT */) != 0; // optional from v8.3
bool has_flagm = (hwcap & (1 << 27) /* HWCAP_FLAGM */) != 0; // optional from v8.1
bool has_ilrcpc = (hwcap & (1 << 26) /* HWCAP_ILRCPC */) != 0; // optional from v8.2
// ARMv8.5-A
bool has_bti = (hwcap2 & (1 << 17) /* HWCAP2_BTI */) != 0; // optional from v8.4
bool has_sb = (hwcap & (1 << 29) /* HWCAP_SB */) != 0; // optional from v8.0
bool has_bti = (hwcap2 & (1 << 17) /* HWCAP2_BTI */) != 0; // optional from v8.4
bool has_sb = (hwcap & (1 << 29) /* HWCAP_SB */) != 0; // optional from v8.0
bool has_dcpodp = (hwcap2 & (1 << 0) /* HWCAP2_DCPODP */) != 0; // optional from v8.1
bool has_flagm2 = (hwcap2 & (1 << 7) /* HWCAP2_FLAGM2 */) != 0; // optional from v8.4
bool has_frint = (hwcap2 & (1 << 8) /* HWCAP2_FRINT */) != 0; // optional from v8.4
bool has_frint = (hwcap2 & (1 << 8) /* HWCAP2_FRINT */) != 0; // optional from v8.4
// ARMv9.0-A
bool has_sve2 = (hwcap2 & (1 << 1) /* HWCAP2_SVE2 */) != 0;
@@ -221,7 +240,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
bool has_f8e5m2 = (hwcap2 & (1UL << 56) /* HWCAP2_F8E5M2 */) != 0; // optional from v9.2
// ARMv9.6-A
bool has_cmpbr = (hwcap & (1UL << 33) /* HWCAP_CMPBR */) != 0; // optional from v9.5
bool has_cmpbr = (hwcap & (1UL << 33) /* HWCAP_CMPBR */) != 0; // optional from v9.5
bool has_fprcvt = (hwcap & (1UL << 34) /* HWCAP_FPRCVT */) != 0; // optional from v9.5
if (has_sve2 || has_sme) {
@@ -266,77 +285,78 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
}
}
}
#elif __APPLE__
#include <sys/sysctl.h>
# elif __APPLE__
# include <sys/sysctl.h>
// #include <arm/cpu_capabilities_public.h> // Not available in macOS 14-
void ffCPUDetectByCpuid(FFCPUResult* cpu)
{
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
uint64_t caps[2] = {0}; // 80-bit capability mask, split into two 64-bit values
size_t size = sizeof(caps);
if (sysctlbyname("hw.optional.arm.caps", caps, &size, NULL, 0) != 0) return;
if (sysctlbyname("hw.optional.arm.caps", caps, &size, NULL, 0) != 0) {
return;
}
// Helper macro to test bit in 80-bit capability mask
#define FF_HAS_CAP(bit) \
(((bit) < 64) ? ((caps[0] >> (bit)) & 1ULL) : ((caps[1] >> ((bit) - 64U)) & 1ULL))
// Helper macro to test bit in 80-bit capability mask
# define FF_HAS_CAP(bit) \
(((bit) < 64) ? ((caps[0] >> (bit)) & 1ULL) : ((caps[1] >> ((bit) - 64U)) & 1ULL))
cpu->march = "unknown";
// ARMv8-A
bool has_fp = FF_HAS_CAP(50); /* CAP_BIT_AdvSIMD_HPFPCvt */ // Full FP16 support (implies FP/ASIMD)
bool has_asimd = FF_HAS_CAP(49); /* CAP_BIT_AdvSIMD */ // Advanced SIMD (NEON)
bool has_fp = FF_HAS_CAP(50); /* CAP_BIT_AdvSIMD_HPFPCvt */ // Full FP16 support (implies FP/ASIMD)
bool has_asimd = FF_HAS_CAP(49); /* CAP_BIT_AdvSIMD */ // Advanced SIMD (NEON)
// ARMv8.1-A
bool has_lse = FF_HAS_CAP(6); /* CAP_BIT_FEAT_LSE */ // Large System Extensions, optional in v8.0
bool has_crc32 = FF_HAS_CAP(51); /* CAP_BIT_FEAT_CRC32 */ // CRC32 instructions, optional in v8.0
bool has_rdm = FF_HAS_CAP(5); /* CAP_BIT_FEAT_RDM */ // AdvSIMD rounding double multiply accumulate, optional in v8.0
bool has_lse = FF_HAS_CAP(6); /* CAP_BIT_FEAT_LSE */ // Large System Extensions, optional in v8.0
bool has_crc32 = FF_HAS_CAP(51); /* CAP_BIT_FEAT_CRC32 */ // CRC32 instructions, optional in v8.0
bool has_rdm = FF_HAS_CAP(5); /* CAP_BIT_FEAT_RDM */ // AdvSIMD rounding double multiply accumulate, optional in v8.0
// ARMv8.2-A
bool has_fp16 = FF_HAS_CAP(34); /* CAP_BIT_FEAT_FP16 */ // Half-precision FP support, optional
bool has_dpb = FF_HAS_CAP(22); /* CAP_BIT_FEAT_DPB */ // DC CVAP, optional from v8.1
bool has_fp16 = FF_HAS_CAP(34); /* CAP_BIT_FEAT_FP16 */ // Half-precision FP support, optional
bool has_dpb = FF_HAS_CAP(22); /* CAP_BIT_FEAT_DPB */ // DC CVAP, optional from v8.1
// ARMv8.3-A
bool has_pauth = FF_HAS_CAP(19); /* CAP_BIT_FEAT_PAuth */ // Pointer Authentication (PAC), optional from v8.2
bool has_lrcpc = FF_HAS_CAP(15); /* CAP_BIT_FEAT_LRCPC */ // LDAPR/LR with RCPC semantics, optional from v8.2
bool has_fcma = FF_HAS_CAP(17); /* CAP_BIT_FEAT_FCMA */ // Complex number multiply-add, optional from v8.2
bool has_jscvt = FF_HAS_CAP(18); /* CAP_BIT_FEAT_JSCVT */ // JavaScript-style conversion (FJCVTZS), optional from v8.2
bool has_pauth = FF_HAS_CAP(19); /* CAP_BIT_FEAT_PAuth */ // Pointer Authentication (PAC), optional from v8.2
bool has_lrcpc = FF_HAS_CAP(15); /* CAP_BIT_FEAT_LRCPC */ // LDAPR/LR with RCPC semantics, optional from v8.2
bool has_fcma = FF_HAS_CAP(17); /* CAP_BIT_FEAT_FCMA */ // Complex number multiply-add, optional from v8.2
bool has_jscvt = FF_HAS_CAP(18); /* CAP_BIT_FEAT_JSCVT */ // JavaScript-style conversion (FJCVTZS), optional from v8.2
// ARMv8.4-A
bool has_lse2 = FF_HAS_CAP(30); /* CAP_BIT_FEAT_LSE2 */ // Large System Extensions version 2, optional from v8.2
bool has_dit = FF_HAS_CAP(33); /* CAP_BIT_FEAT_DIT */ // Data Independent Timing, optional from v8.3
bool has_flagm = FF_HAS_CAP(0); /* CAP_BIT_FEAT_FlagM */ // Flag manipulation (FMOV/FCVT), optional from v8.1
bool has_lrcpc2 = FF_HAS_CAP(16); /* CAP_BIT_FEAT_LRCPC2 */ // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
bool has_lse2 = FF_HAS_CAP(30); /* CAP_BIT_FEAT_LSE2 */ // Large System Extensions version 2, optional from v8.2
bool has_dit = FF_HAS_CAP(33); /* CAP_BIT_FEAT_DIT */ // Data Independent Timing, optional from v8.3
bool has_flagm = FF_HAS_CAP(0); /* CAP_BIT_FEAT_FlagM */ // Flag manipulation (FMOV/FCVT), optional from v8.1
bool has_lrcpc2 = FF_HAS_CAP(16); /* CAP_BIT_FEAT_LRCPC2 */ // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
// ARMv8.5-A
bool has_bti = FF_HAS_CAP(36); /* CAP_BIT_FEAT_BTI */ // Branch Target Identification, optional from v8.4
bool has_sb = FF_HAS_CAP(13); /* CAP_BIT_FEAT_SB */ // Speculative Barrier, optional from v8.0
bool has_dpb2 = FF_HAS_CAP(23); /* CAP_BIT_FEAT_DPB2 */ // DC CVADP (DPB2), optional from v8.1
bool has_flagm2 = FF_HAS_CAP(1); /* CAP_BIT_FEAT_FlagM2 */ // Enhanced FlagM, optional from v8.4
bool has_frintts = FF_HAS_CAP(14); /* CAP_BIT_FEAT_FRINTTS */ // Floating-point to integer instructions, optional from v8.4
bool has_bti = FF_HAS_CAP(36); /* CAP_BIT_FEAT_BTI */ // Branch Target Identification, optional from v8.4
bool has_sb = FF_HAS_CAP(13); /* CAP_BIT_FEAT_SB */ // Speculative Barrier, optional from v8.0
bool has_dpb2 = FF_HAS_CAP(23); /* CAP_BIT_FEAT_DPB2 */ // DC CVADP (DPB2), optional from v8.1
bool has_flagm2 = FF_HAS_CAP(1); /* CAP_BIT_FEAT_FlagM2 */ // Enhanced FlagM, optional from v8.4
bool has_frintts = FF_HAS_CAP(14); /* CAP_BIT_FEAT_FRINTTS */ // Floating-point to integer instructions, optional from v8.4
// ARMv9.0-A
bool has_sve2 = false; // Not exposed and not supported by Apple M4
bool has_sve2 = false; // Not exposed and not supported by Apple M4
// ARMv9.1-A
// ARMv8.6-A
bool has_bf16 = FF_HAS_CAP(24); /* CAP_BIT_FEAT_BF16 */ // Brain float16, optional from v8.2
bool has_i8mm = FF_HAS_CAP(25); /* CAP_BIT_FEAT_I8MM */ // Int8 Matrix Multiply, optional from v8.1
bool has_bf16 = FF_HAS_CAP(24); /* CAP_BIT_FEAT_BF16 */ // Brain float16, optional from v8.2
bool has_i8mm = FF_HAS_CAP(25); /* CAP_BIT_FEAT_I8MM */ // Int8 Matrix Multiply, optional from v8.1
// ARMv8.7-A
bool has_afp = FF_HAS_CAP(29); /* CAP_BIT_FEAT_AFP */ // Alternate FP16 (FEXPA), optional from v8.6
bool has_afp = FF_HAS_CAP(29); /* CAP_BIT_FEAT_AFP */ // Alternate FP16 (FEXPA), optional from v8.6
// ARMv9.2-A
bool has_sme = FF_HAS_CAP(40); /* CAP_BIT_FEAT_SME */ // Scalable Matrix Extension, optional from v9.2
bool has_sme = FF_HAS_CAP(40); /* CAP_BIT_FEAT_SME */ // Scalable Matrix Extension, optional from v9.2
// ARMv9.3-A
bool has_sme2 = FF_HAS_CAP(41); /* CAP_BIT_FEAT_SME2 */ // SME2, optional from v9.2
bool has_sme2 = FF_HAS_CAP(41); /* CAP_BIT_FEAT_SME2 */ // SME2, optional from v9.2
// ARMv8.8-A
bool has_hbc = FF_HAS_CAP(64); /* CAP_BIT_FEAT_HBC */ // Hinted conditional branches, optional from v8.7
bool has_hbc = FF_HAS_CAP(64); /* CAP_BIT_FEAT_HBC */ // Hinted conditional branches, optional from v8.7
// ARMv8.9-A
bool has_cssc = FF_HAS_CAP(67); /* CAP_BIT_FEAT_CSSC */ // Common Short String Compare, optional from v8.7
bool has_cssc = FF_HAS_CAP(67); /* CAP_BIT_FEAT_CSSC */ // Common Short String Compare, optional from v8.7
// ARMv9.4-A+ are not exposed yet
@@ -376,85 +396,82 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
}
}
#undef HAS_CAP
# undef HAS_CAP
}
#elif _WIN32
#include <processthreadsapi.h>
# elif _WIN32
# include <processthreadsapi.h>
// Missing from winnt.h of MinGW-w64
#define PF_ARM_LSE2_AVAILABLE 62
#define PF_RESERVED_FEATURE 63
#define PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE 64
#define PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE 65
#define PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE 66
#define PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE 67
#define PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE 68
#define PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE 69
#define PF_ARM_SME_INSTRUCTIONS_AVAILABLE 70
#define PF_ARM_SME2_INSTRUCTIONS_AVAILABLE 71
#define PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE 72
#define PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE 73
#define PF_ARM_SME_AES_INSTRUCTIONS_AVAILABLE 74
#define PF_ARM_SME_SBITPERM_INSTRUCTIONS_AVAILABLE 75
#define PF_ARM_SME_SF8MM4_INSTRUCTIONS_AVAILABLE 76
#define PF_ARM_SME_SF8MM8_INSTRUCTIONS_AVAILABLE 77
#define PF_ARM_SME_SF8DP2_INSTRUCTIONS_AVAILABLE 78
#define PF_ARM_SME_SF8DP4_INSTRUCTIONS_AVAILABLE 79
#define PF_ARM_SME_SF8FMA_INSTRUCTIONS_AVAILABLE 80
#define PF_ARM_SME_F8F32_INSTRUCTIONS_AVAILABLE 81
#define PF_ARM_SME_F8F16_INSTRUCTIONS_AVAILABLE 82
#define PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE 83
#define PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE 84
#define PF_ARM_SME_F64F64_INSTRUCTIONS_AVAILABLE 85
#define PF_ARM_SME_I16I64_INSTRUCTIONS_AVAILABLE 86
#define PF_ARM_SME_LUTv2_INSTRUCTIONS_AVAILABLE 87
#define PF_ARM_SME_FA64_INSTRUCTIONS_AVAILABLE 88
# define PF_ARM_LSE2_AVAILABLE 62
# define PF_RESERVED_FEATURE 63
# define PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE 64
# define PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE 65
# define PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE 66
# define PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE 67
# define PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE 68
# define PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE 69
# define PF_ARM_SME_INSTRUCTIONS_AVAILABLE 70
# define PF_ARM_SME2_INSTRUCTIONS_AVAILABLE 71
# define PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE 72
# define PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE 73
# define PF_ARM_SME_AES_INSTRUCTIONS_AVAILABLE 74
# define PF_ARM_SME_SBITPERM_INSTRUCTIONS_AVAILABLE 75
# define PF_ARM_SME_SF8MM4_INSTRUCTIONS_AVAILABLE 76
# define PF_ARM_SME_SF8MM8_INSTRUCTIONS_AVAILABLE 77
# define PF_ARM_SME_SF8DP2_INSTRUCTIONS_AVAILABLE 78
# define PF_ARM_SME_SF8DP4_INSTRUCTIONS_AVAILABLE 79
# define PF_ARM_SME_SF8FMA_INSTRUCTIONS_AVAILABLE 80
# define PF_ARM_SME_F8F32_INSTRUCTIONS_AVAILABLE 81
# define PF_ARM_SME_F8F16_INSTRUCTIONS_AVAILABLE 82
# define PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE 83
# define PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE 84
# define PF_ARM_SME_F64F64_INSTRUCTIONS_AVAILABLE 85
# define PF_ARM_SME_I16I64_INSTRUCTIONS_AVAILABLE 86
# define PF_ARM_SME_LUTv2_INSTRUCTIONS_AVAILABLE 87
# define PF_ARM_SME_FA64_INSTRUCTIONS_AVAILABLE 88
void ffCPUDetectByCpuid(FFCPUResult* cpu)
{
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
// ARMv8-A
bool has_vfp = IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE); // Implies basic FP support
bool has_neon = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE); // NEON (ASIMD)
bool has_vfp = IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE); // Implies basic FP support
bool has_neon = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE); // NEON (ASIMD)
// ARMv8.1-A
bool has_atomics = IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE); // LSE atomics
bool has_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); // CRC32
bool has_atomics = IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE); // LSE atomics
bool has_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); // CRC32
// ARMv8.2-A
bool has_fp16 = IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE); // Half-precision FP
bool has_fp16 = IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE); // Half-precision FP
// ARMv8.3-A
bool has_lrcpc = IsProcessorFeaturePresent(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE); // LDAPR/LR with RCPC semantics
bool has_jscvt = IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE); // FJCVTZS
bool has_lrcpc = IsProcessorFeaturePresent(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE); // LDAPR/LR with RCPC semantics
bool has_jscvt = IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE); // FJCVTZS
// ARMv8.4-A
// My CPU (Apple M1 Pro in VM) does support LSE2, but Windows doesn't detect it for some reason
bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
bool has_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); // DotProd, optional from v8.1 (*)
bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
bool has_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); // DotProd, optional from v8.1 (*)
// ARMv9.0-A
bool has_sve2 = IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE); // SVE2
bool has_sve2 = IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE); // SVE2
// ARMv9.1-A
// ARMv8.6-A
bool has_bf16 = IsProcessorFeaturePresent(PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE); // BF16, optional from v8.2
bool has_i8mm = IsProcessorFeaturePresent(PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE); // Int8 matrix multiply, optional from v8.2
bool has_bf16 = IsProcessorFeaturePresent(PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE); // BF16, optional from v8.2
bool has_i8mm = IsProcessorFeaturePresent(PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE); // Int8 matrix multiply, optional from v8.2
// ARMv8.7-A
bool has_ebf16 = IsProcessorFeaturePresent(PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE); // Extended BFloat16 behaviors, optional from v8.2
bool has_ebf16 = IsProcessorFeaturePresent(PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE); // Extended BFloat16 behaviors, optional from v8.2
// ARMv9.2-A
bool has_sme = IsProcessorFeaturePresent(PF_ARM_SME_INSTRUCTIONS_AVAILABLE); // SME
bool has_sme = IsProcessorFeaturePresent(PF_ARM_SME_INSTRUCTIONS_AVAILABLE); // SME
// ARMv9.3-A
bool has_sme2 = IsProcessorFeaturePresent(PF_ARM_SME2_INSTRUCTIONS_AVAILABLE); // SME2
bool has_sme2 = IsProcessorFeaturePresent(PF_ARM_SME2_INSTRUCTIONS_AVAILABLE); // SME2
// ARMv9.4-A
bool has_sme2p1 = IsProcessorFeaturePresent(PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE); // SME2.1
bool has_sme2p1 = IsProcessorFeaturePresent(PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE); // SME2.1
if (has_sve2 || has_sme)
{
if (has_sve2 || has_sme) {
// ARMv9 family
if (has_sme2p1) {
cpu->march = "ARMv9.4-A";
@@ -467,9 +484,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
} else {
cpu->march = "ARMv9.0-A";
}
}
else
{
} else {
// ARMv8 family
if (has_ebf16) {
cpu->march = "ARMv8.7-A";
@@ -488,17 +503,15 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
}
}
}
#else
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
{
# else
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu) {
// Unsupported system
}
#endif
# endif
#else
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
{
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu) {
// Unsupported architecture
}
+3 -5
View File
@@ -5,14 +5,12 @@
#define FF_CPU_TEMP_UNSET (-DBL_MAX)
typedef struct FFCPUCore
{
typedef struct FFCPUCore {
uint32_t freq;
uint32_t count;
} FFCPUCore;
typedef struct FFCPUResult
{
typedef struct FFCPUResult {
FFstrbuf name;
FFstrbuf vendor;
const char* march; // Microarchitecture
@@ -24,7 +22,7 @@ typedef struct FFCPUResult
uint16_t numaNodes;
uint32_t frequencyBase; // GHz
uint32_t frequencyMax; // GHz
uint32_t frequencyMax; // GHz
FFCPUCore coreTypes[16]; // number of P cores, E cores, etc.
+65 -51
View File
@@ -3,106 +3,114 @@
#include "common/apple/smc_temps.h"
#include "common/stringUtils.h"
static double detectCpuTemp(const FFCPUOptions* options, const FFstrbuf* cpuName)
{
static double detectCpuTemp(const FFCPUOptions* options, const FFstrbuf* cpuName) {
double result = 0;
const char* error = NULL;
if (options->tempSensor.length)
{
if (options->tempSensor.length) {
error = ffDetectSmcSpecificTemp(options->tempSensor.chars, &result);
}
else
{
if (ffStrbufStartsWithS(cpuName, "Apple M"))
{
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
{
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
default: error = "Unsupported Apple Silicon CPU";
} else {
if (ffStrbufStartsWithS(cpuName, "Apple M")) {
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10)) {
case 1:
error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result);
break;
case 2:
error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result);
break;
case 3:
error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result);
break;
case 4:
error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result);
break;
default:
error = "Unsupported Apple Silicon CPU";
}
}
else // PPC?
} else { // PPC?
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
}
}
if (error)
if (error) {
return FF_CPU_TEMP_UNSET;
}
return result;
}
#ifdef __aarch64__
#include "common/apple/cf_helpers.h"
# include "common/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
# include <IOKit/IOKitLib.h>
static const char* detectFrequency(FFCPUResult* cpu)
{
static const char* detectFrequency(FFCPUResult* cpu) {
// https://github.com/giampaolo/psutil/pull/2222/files
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
if (!entryDevice)
if (!entryDevice) {
return "IOServiceGetMatchingService() failed";
}
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) {
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
}
FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, kNilOptions);
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID())
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID()) {
return "\"voltage-states5-sram\" in \"pmgr\" is not found";
}
// voltage-states5-sram stores supported <frequency / voltage> pairs of pcores from the lowest to the highest
// voltage-states1-sram stores ecores'
CFIndex propLength = CFDataGetLength(freqProperty);
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0)
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) {
return "Invalid \"voltage-states5-sram\" length";
}
uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty);
uint32_t pMax = *pStart;
for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */)
for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */) {
pMax = pMax > pStart[i] ? pMax : pStart[i];
}
if (pMax > 0)
{
if (pMax > 100000000) // Assume that pMax is in Hz, M1~M3
if (pMax > 0) {
if (pMax > 100000000) { // Assume that pMax is in Hz, M1~M3
cpu->frequencyMax = pMax / 1000 / 1000;
else // Assume that pMax is in kHz, M4 and later (#1394)
} else { // Assume that pMax is in kHz, M4 and later (#1394)
cpu->frequencyMax = pMax / 1000;
}
}
return NULL;
}
#else
static const char* detectFrequency(FFCPUResult* cpu)
{
static const char* detectFrequency(FFCPUResult* cpu) {
cpu->frequencyBase = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency", 0) / 1000 / 1000);
cpu->frequencyMax = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000 / 1000);
if(cpu->frequencyBase == 0)
{
if (cpu->frequencyBase == 0) {
unsigned current = 0;
size_t size = sizeof(current);
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, &current, &size, NULL, 0) == 0)
if (sysctl((int[]) {CTL_HW, HW_CPU_FREQ}, 2, &current, &size, NULL, 0) == 0) {
cpu->frequencyBase = (uint32_t) (current / 1000 / 1000);
}
}
return NULL;
}
#endif
static const char* detectCoreCount(FFCPUResult* cpu)
{
static const char* detectCoreCount(FFCPUResult* cpu) {
uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0);
if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed";
if (nPerfLevels <= 0) {
return "sysctl(hw.nperflevels) failed";
}
char sysctlKey[] = "hw.perflevelN.logicalcpu";
if (nPerfLevels > ARRAY_SIZE(cpu->coreTypes))
if (nPerfLevels > ARRAY_SIZE(cpu->coreTypes)) {
nPerfLevels = ARRAY_SIZE(cpu->coreTypes);
for (uint32_t i = 0; i < nPerfLevels; ++i)
{
}
for (uint32_t i = 0; i < nPerfLevels; ++i) {
sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i);
cpu->coreTypes[i] = (FFCPUCore) {
.freq = nPerfLevels - i,
@@ -112,31 +120,37 @@ static const char* detectCoreCount(FFCPUResult* cpu)
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL)
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL) {
return "sysctlbyname(machdep.cpu.brand_string) failed";
}
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
cpu->packages = (uint16_t) ffSysctlGetInt("hw.packages", 1);
if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple "))
if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple ")) {
ffStrbufAppendS(&cpu->vendor, "Apple");
}
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
if(cpu->coresPhysical == 1)
if (cpu->coresPhysical == 1) {
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
}
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
if(cpu->coresLogical == 1)
if (cpu->coresLogical == 1) {
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
}
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
if(cpu->coresOnline == 1)
if (cpu->coresOnline == 1) {
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
}
ffCPUDetectByCpuid(cpu);
detectFrequency(cpu);
if (options->showPeCoreCount) detectCoreCount(cpu);
if (options->showPeCoreCount) {
detectCoreCount(cpu);
}
cpu->temperature = options->temp ? detectCpuTemp(options, &cpu->name) : FF_CPU_TEMP_UNSET;
+528 -318
View File
@@ -5,374 +5,584 @@
// https://github.com/util-linux/util-linux/blob/master/sys-utils/lscpu-arm.c
// We use the util-linux's data but not its code. Call me if it violates util-linux's GPL license.
static const char* hwImplId2Vendor(uint32_t implId)
{
switch (implId)
{
case 0x41: return "ARM";
case 0x42: return "Broadcom";
case 0x43: return "Cavium";
case 0x44: return "DEC";
case 0x46: return "FUJITSU";
case 0x48: return "HiSilicon";
case 0x49: return "Infineon";
case 0x4d: return "Motorola";
case 0x4e: return "NVIDIA";
case 0x50: return "APM";
case 0x51: return "Qualcomm";
case 0x53: return "Samsung";
case 0x56: return "Marvell";
case 0x61: return "Apple";
case 0x66: return "Faraday";
case 0x69: return "Intel";
case 0x6D: return "Microsoft";
case 0x70: return "Phytium";
case 0xc0: return "Ampere";
default: return "Unknown";
static const char* hwImplId2Vendor(uint32_t implId) {
switch (implId) {
case 0x41:
return "ARM";
case 0x42:
return "Broadcom";
case 0x43:
return "Cavium";
case 0x44:
return "DEC";
case 0x46:
return "FUJITSU";
case 0x48:
return "HiSilicon";
case 0x49:
return "Infineon";
case 0x4d:
return "Motorola";
case 0x4e:
return "NVIDIA";
case 0x50:
return "APM";
case 0x51:
return "Qualcomm";
case 0x53:
return "Samsung";
case 0x56:
return "Marvell";
case 0x61:
return "Apple";
case 0x66:
return "Faraday";
case 0x69:
return "Intel";
case 0x6D:
return "Microsoft";
case 0x70:
return "Phytium";
case 0xc0:
return "Ampere";
default:
return "Unknown";
}
}
static const char* armPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x810: return "ARM810";
case 0x920: return "ARM920";
case 0x922: return "ARM922";
case 0x926: return "ARM926";
case 0x940: return "ARM940";
case 0x946: return "ARM946";
case 0x966: return "ARM966";
case 0xa20: return "ARM1020";
case 0xa22: return "ARM1022";
case 0xa26: return "ARM1026";
case 0xb02: return "ARM11-MPCore";
case 0xb36: return "ARM1136";
case 0xb56: return "ARM1156";
case 0xb76: return "ARM1176";
case 0xc05: return "Cortex-A5";
case 0xc07: return "Cortex-A7";
case 0xc08: return "Cortex-A8";
case 0xc09: return "Cortex-A9";
case 0xc0d: return "Cortex-A17"; /* Originally A12 */
case 0xc0f: return "Cortex-A15";
case 0xc0e: return "Cortex-A17";
case 0xc14: return "Cortex-R4";
case 0xc15: return "Cortex-R5";
case 0xc17: return "Cortex-R7";
case 0xc18: return "Cortex-R8";
case 0xc20: return "Cortex-M0";
case 0xc21: return "Cortex-M1";
case 0xc23: return "Cortex-M3";
case 0xc24: return "Cortex-M4";
case 0xc27: return "Cortex-M7";
case 0xc60: return "Cortex-M0+";
case 0xd01: return "Cortex-A32";
case 0xd02: return "Cortex-A34";
case 0xd03: return "Cortex-A53";
case 0xd04: return "Cortex-A35";
case 0xd05: return "Cortex-A55";
case 0xd06: return "Cortex-A65";
case 0xd07: return "Cortex-A57";
case 0xd08: return "Cortex-A72";
case 0xd09: return "Cortex-A73";
case 0xd0a: return "Cortex-A75";
case 0xd0b: return "Cortex-A76";
case 0xd0c: return "Neoverse-N1";
case 0xd0d: return "Cortex-A77";
case 0xd0e: return "Cortex-A76AE";
case 0xd13: return "Cortex-R52";
case 0xd14: return "Cortex-R82AE";
case 0xd15: return "Cortex-R82";
case 0xd16: return "Cortex-R52+";
case 0xd20: return "Cortex-M23";
case 0xd21: return "Cortex-M33";
case 0xd24: return "Cortex-M52";
case 0xd22: return "Cortex-M55";
case 0xd23: return "Cortex-M85";
case 0xd40: return "Neoverse-V1";
case 0xd41: return "Cortex-A78";
case 0xd42: return "Cortex-A78AE";
case 0xd43: return "Cortex-A65AE";
case 0xd44: return "Cortex-X1";
case 0xd46: return "Cortex-A510";
case 0xd47: return "Cortex-A710";
case 0xd48: return "Cortex-X2";
case 0xd49: return "Neoverse-N2";
case 0xd4a: return "Neoverse-E1";
case 0xd4b: return "Cortex-A78C";
case 0xd4c: return "Cortex-X1C";
case 0xd4d: return "Cortex-A715";
case 0xd4e: return "Cortex-X3";
case 0xd4f: return "Neoverse-V2";
case 0xd80: return "Cortex-A520";
case 0xd81: return "Cortex-A720";
case 0xd82: return "Cortex-X4";
case 0xd83: return "Neoverse-V3AE";
case 0xd84: return "Neoverse-V3";
case 0xd85: return "Cortex-X925";
case 0xd87: return "Cortex-A725";
case 0xd88: return "Cortex-A520AE";
case 0xd89: return "Cortex-A720AE";
case 0xd8a: return "C1-Nano";
case 0xd8b: return "C1-Pro";
case 0xd8c: return "C1-Ultra";
case 0xd8e: return "Neoverse-N3";
case 0xd8f: return "Cortex-A320";
case 0xd90: return "C1-Premium";
default: return NULL;
static const char* armPartId2name(uint32_t partId) {
switch (partId) {
case 0x810:
return "ARM810";
case 0x920:
return "ARM920";
case 0x922:
return "ARM922";
case 0x926:
return "ARM926";
case 0x940:
return "ARM940";
case 0x946:
return "ARM946";
case 0x966:
return "ARM966";
case 0xa20:
return "ARM1020";
case 0xa22:
return "ARM1022";
case 0xa26:
return "ARM1026";
case 0xb02:
return "ARM11-MPCore";
case 0xb36:
return "ARM1136";
case 0xb56:
return "ARM1156";
case 0xb76:
return "ARM1176";
case 0xc05:
return "Cortex-A5";
case 0xc07:
return "Cortex-A7";
case 0xc08:
return "Cortex-A8";
case 0xc09:
return "Cortex-A9";
case 0xc0d:
return "Cortex-A17"; /* Originally A12 */
case 0xc0f:
return "Cortex-A15";
case 0xc0e:
return "Cortex-A17";
case 0xc14:
return "Cortex-R4";
case 0xc15:
return "Cortex-R5";
case 0xc17:
return "Cortex-R7";
case 0xc18:
return "Cortex-R8";
case 0xc20:
return "Cortex-M0";
case 0xc21:
return "Cortex-M1";
case 0xc23:
return "Cortex-M3";
case 0xc24:
return "Cortex-M4";
case 0xc27:
return "Cortex-M7";
case 0xc60:
return "Cortex-M0+";
case 0xd01:
return "Cortex-A32";
case 0xd02:
return "Cortex-A34";
case 0xd03:
return "Cortex-A53";
case 0xd04:
return "Cortex-A35";
case 0xd05:
return "Cortex-A55";
case 0xd06:
return "Cortex-A65";
case 0xd07:
return "Cortex-A57";
case 0xd08:
return "Cortex-A72";
case 0xd09:
return "Cortex-A73";
case 0xd0a:
return "Cortex-A75";
case 0xd0b:
return "Cortex-A76";
case 0xd0c:
return "Neoverse-N1";
case 0xd0d:
return "Cortex-A77";
case 0xd0e:
return "Cortex-A76AE";
case 0xd13:
return "Cortex-R52";
case 0xd14:
return "Cortex-R82AE";
case 0xd15:
return "Cortex-R82";
case 0xd16:
return "Cortex-R52+";
case 0xd20:
return "Cortex-M23";
case 0xd21:
return "Cortex-M33";
case 0xd24:
return "Cortex-M52";
case 0xd22:
return "Cortex-M55";
case 0xd23:
return "Cortex-M85";
case 0xd40:
return "Neoverse-V1";
case 0xd41:
return "Cortex-A78";
case 0xd42:
return "Cortex-A78AE";
case 0xd43:
return "Cortex-A65AE";
case 0xd44:
return "Cortex-X1";
case 0xd46:
return "Cortex-A510";
case 0xd47:
return "Cortex-A710";
case 0xd48:
return "Cortex-X2";
case 0xd49:
return "Neoverse-N2";
case 0xd4a:
return "Neoverse-E1";
case 0xd4b:
return "Cortex-A78C";
case 0xd4c:
return "Cortex-X1C";
case 0xd4d:
return "Cortex-A715";
case 0xd4e:
return "Cortex-X3";
case 0xd4f:
return "Neoverse-V2";
case 0xd80:
return "Cortex-A520";
case 0xd81:
return "Cortex-A720";
case 0xd82:
return "Cortex-X4";
case 0xd83:
return "Neoverse-V3AE";
case 0xd84:
return "Neoverse-V3";
case 0xd85:
return "Cortex-X925";
case 0xd87:
return "Cortex-A725";
case 0xd88:
return "Cortex-A520AE";
case 0xd89:
return "Cortex-A720AE";
case 0xd8a:
return "C1-Nano";
case 0xd8b:
return "C1-Pro";
case 0xd8c:
return "C1-Ultra";
case 0xd8e:
return "Neoverse-N3";
case 0xd8f:
return "Cortex-A320";
case 0xd90:
return "C1-Premium";
default:
return NULL;
}
}
static const char* brcmPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x0f: return "Brahma-B15";
case 0x100: return "Brahma-B53";
case 0x516: return "ThunderX2";
default: return NULL;
static const char* brcmPartId2name(uint32_t partId) {
switch (partId) {
case 0x0f:
return "Brahma-B15";
case 0x100:
return "Brahma-B53";
case 0x516:
return "ThunderX2";
default:
return NULL;
}
}
static const char* decPartId2name(uint32_t partId)
{
switch (partId)
{
case 0xa10: return "SA110";
case 0xa11: return "SA1100";
default: return NULL;
static const char* decPartId2name(uint32_t partId) {
switch (partId) {
case 0xa10:
return "SA110";
case 0xa11:
return "SA1100";
default:
return NULL;
}
}
static const char* caviumPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x0a0: return "ThunderX";
case 0x0a1: return "ThunderX-88XX";
case 0x0a2: return "ThunderX-81XX";
case 0x0a3: return "ThunderX-83XX";
case 0x0af: return "ThunderX2-99xx";
case 0x0b0: return "OcteonTX2";
case 0x0b1: return "OcteonTX2-98XX";
case 0x0b2: return "OcteonTX2-96XX";
case 0x0b3: return "OcteonTX2-95XX";
case 0x0b4: return "OcteonTX2-95XXN";
case 0x0b5: return "OcteonTX2-95XXMM";
case 0x0b6: return "OcteonTX2-95XXO";
case 0x0b8: return "ThunderX3-T110";
default: return NULL;
static const char* caviumPartId2name(uint32_t partId) {
switch (partId) {
case 0x0a0:
return "ThunderX";
case 0x0a1:
return "ThunderX-88XX";
case 0x0a2:
return "ThunderX-81XX";
case 0x0a3:
return "ThunderX-83XX";
case 0x0af:
return "ThunderX2-99xx";
case 0x0b0:
return "OcteonTX2";
case 0x0b1:
return "OcteonTX2-98XX";
case 0x0b2:
return "OcteonTX2-96XX";
case 0x0b3:
return "OcteonTX2-95XX";
case 0x0b4:
return "OcteonTX2-95XXN";
case 0x0b5:
return "OcteonTX2-95XXMM";
case 0x0b6:
return "OcteonTX2-95XXO";
case 0x0b8:
return "ThunderX3-T110";
default:
return NULL;
}
}
static const char* apmPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x000: return "X-Gene";
default: return NULL;
static const char* apmPartId2name(uint32_t partId) {
switch (partId) {
case 0x000:
return "X-Gene";
default:
return NULL;
}
}
static const char* qcomPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x001: return "Oryon 1";
case 0x002: return "Oryon 2";
case 0x00f: return "Scorpion";
case 0x02d: return "Scorpion";
case 0x04d: return "Krait";
case 0x06f: return "Krait";
case 0x201: return "Kryo";
case 0x205: return "Kryo";
case 0x211: return "Kryo";
case 0x800: return "Falkor-V1/Kryo";
case 0x801: return "Kryo-V2";
case 0x802: return "Kryo-3XX-Gold";
case 0x803: return "Kryo-3XX-Silver";
case 0x804: return "Kryo-4XX-Gold";
case 0x805: return "Kryo-4XX-Silver";
case 0xc00: return "Falkor";
case 0xc01: return "Saphira";
default: return NULL;
static const char* qcomPartId2name(uint32_t partId) {
switch (partId) {
case 0x001:
return "Oryon 1";
case 0x002:
return "Oryon 2";
case 0x00f:
return "Scorpion";
case 0x02d:
return "Scorpion";
case 0x04d:
return "Krait";
case 0x06f:
return "Krait";
case 0x201:
return "Kryo";
case 0x205:
return "Kryo";
case 0x211:
return "Kryo";
case 0x800:
return "Falkor-V1/Kryo";
case 0x801:
return "Kryo-V2";
case 0x802:
return "Kryo-3XX-Gold";
case 0x803:
return "Kryo-3XX-Silver";
case 0x804:
return "Kryo-4XX-Gold";
case 0x805:
return "Kryo-4XX-Silver";
case 0xc00:
return "Falkor";
case 0xc01:
return "Saphira";
default:
return NULL;
}
}
static const char* samsungPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x001: return "Exynos-M1";
case 0x002: return "Exynos-M3";
case 0x003: return "Exynos-M4";
case 0x004: return "Exynos-M5";
default: return NULL;
static const char* samsungPartId2name(uint32_t partId) {
switch (partId) {
case 0x001:
return "Exynos-M1";
case 0x002:
return "Exynos-M3";
case 0x003:
return "Exynos-M4";
case 0x004:
return "Exynos-M5";
default:
return NULL;
}
}
static const char* nvidiaPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x000: return "Denver";
case 0x003: return "Denver-2";
case 0x004: return "Carmel";
case 0x010: return "Olympus";
default: return NULL;
static const char* nvidiaPartId2name(uint32_t partId) {
switch (partId) {
case 0x000:
return "Denver";
case 0x003:
return "Denver-2";
case 0x004:
return "Carmel";
case 0x010:
return "Olympus";
default:
return NULL;
}
}
static const char* marvellPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x131: return "Feroceon-88FR131";
case 0x581: return "PJ4/PJ4b";
case 0x584: return "PJ4B-MP";
default: return NULL;
static const char* marvellPartId2name(uint32_t partId) {
switch (partId) {
case 0x131:
return "Feroceon-88FR131";
case 0x581:
return "PJ4/PJ4b";
case 0x584:
return "PJ4B-MP";
default:
return NULL;
}
}
static const char* applePartId2name(uint32_t partId)
{
switch (partId)
{
case 0x000: return "Swift";
case 0x001: return "Cyclone";
case 0x002: return "Typhoon";
case 0x003: return "Typhoon/Capri";
case 0x004: return "Twister";
case 0x005: return "Twister/Elba/Malta";
case 0x006: return "Hurricane";
case 0x007: return "Hurricane/Myst";
case 0x008: return "Monsoon";
case 0x009: return "Mistral";
case 0x00b: return "Vortex";
case 0x00c: return "Tempest";
case 0x00f: return "Tempest-M9";
case 0x010: return "Vortex/Aruba";
case 0x011: return "Tempest/Aruba";
case 0x012: return "Lightning";
case 0x013: return "Thunder";
case 0x020: return "Icestorm-A14";
case 0x021: return "Firestorm-A14";
case 0x022: return "Icestorm-M1";
case 0x023: return "Firestorm-M1";
case 0x024: return "Icestorm-M1-Pro";
case 0x025: return "Firestorm-M1-Pro";
case 0x026: return "Thunder-M10";
case 0x028: return "Icestorm-M1-Max";
case 0x029: return "Firestorm-M1-Max";
case 0x030: return "Blizzard-A15";
case 0x031: return "Avalanche-A15";
case 0x032: return "Blizzard-M2";
case 0x033: return "Avalanche-M2";
case 0x034: return "Blizzard-M2-Pro";
case 0x035: return "Avalanche-M2-Pro";
case 0x036: return "Sawtooth-A16";
case 0x037: return "Everest-A16";
case 0x038: return "Blizzard-M2-Max";
case 0x039: return "Avalanche-M2-Max";
case 0x046: return "Sawtooth-M11";
case 0x048: return "Sawtooth-M3-Max";
case 0x049: return "Everest-M3-Max";
default: return NULL;
static const char* applePartId2name(uint32_t partId) {
switch (partId) {
case 0x000:
return "Swift";
case 0x001:
return "Cyclone";
case 0x002:
return "Typhoon";
case 0x003:
return "Typhoon/Capri";
case 0x004:
return "Twister";
case 0x005:
return "Twister/Elba/Malta";
case 0x006:
return "Hurricane";
case 0x007:
return "Hurricane/Myst";
case 0x008:
return "Monsoon";
case 0x009:
return "Mistral";
case 0x00b:
return "Vortex";
case 0x00c:
return "Tempest";
case 0x00f:
return "Tempest-M9";
case 0x010:
return "Vortex/Aruba";
case 0x011:
return "Tempest/Aruba";
case 0x012:
return "Lightning";
case 0x013:
return "Thunder";
case 0x020:
return "Icestorm-A14";
case 0x021:
return "Firestorm-A14";
case 0x022:
return "Icestorm-M1";
case 0x023:
return "Firestorm-M1";
case 0x024:
return "Icestorm-M1-Pro";
case 0x025:
return "Firestorm-M1-Pro";
case 0x026:
return "Thunder-M10";
case 0x028:
return "Icestorm-M1-Max";
case 0x029:
return "Firestorm-M1-Max";
case 0x030:
return "Blizzard-A15";
case 0x031:
return "Avalanche-A15";
case 0x032:
return "Blizzard-M2";
case 0x033:
return "Avalanche-M2";
case 0x034:
return "Blizzard-M2-Pro";
case 0x035:
return "Avalanche-M2-Pro";
case 0x036:
return "Sawtooth-A16";
case 0x037:
return "Everest-A16";
case 0x038:
return "Blizzard-M2-Max";
case 0x039:
return "Avalanche-M2-Max";
case 0x046:
return "Sawtooth-M11";
case 0x048:
return "Sawtooth-M3-Max";
case 0x049:
return "Everest-M3-Max";
default:
return NULL;
}
}
static const char* faradayPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x526: return "FA526";
case 0x626: return "FA626";
default: return NULL;
static const char* faradayPartId2name(uint32_t partId) {
switch (partId) {
case 0x526:
return "FA526";
case 0x626:
return "FA626";
default:
return NULL;
}
}
static const char* intelPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x200: return "i80200";
case 0x210: return "PXA250A";
case 0x212: return "PXA210A";
case 0x242: return "i80321-400";
case 0x243: return "i80321-600";
case 0x290: return "PXA250B/PXA26x";
case 0x292: return "PXA210B";
case 0x2c2: return "i80321-400-B0";
case 0x2c3: return "i80321-600-B0";
case 0x2d0: return "PXA250C/PXA255/PXA26x";
case 0x2d2: return "PXA210C";
case 0x411: return "PXA27x";
case 0x41c: return "IPX425-533";
case 0x41d: return "IPX425-400";
case 0x41f: return "IPX425-266";
case 0x682: return "PXA32x";
case 0x683: return "PXA930/PXA935";
case 0x688: return "PXA30x";
case 0x689: return "PXA31x";
case 0xb11: return "SA1110";
case 0xc12: return "IPX1200";
default: return NULL;
static const char* intelPartId2name(uint32_t partId) {
switch (partId) {
case 0x200:
return "i80200";
case 0x210:
return "PXA250A";
case 0x212:
return "PXA210A";
case 0x242:
return "i80321-400";
case 0x243:
return "i80321-600";
case 0x290:
return "PXA250B/PXA26x";
case 0x292:
return "PXA210B";
case 0x2c2:
return "i80321-400-B0";
case 0x2c3:
return "i80321-600-B0";
case 0x2d0:
return "PXA250C/PXA255/PXA26x";
case 0x2d2:
return "PXA210C";
case 0x411:
return "PXA27x";
case 0x41c:
return "IPX425-533";
case 0x41d:
return "IPX425-400";
case 0x41f:
return "IPX425-266";
case 0x682:
return "PXA32x";
case 0x683:
return "PXA930/PXA935";
case 0x688:
return "PXA30x";
case 0x689:
return "PXA31x";
case 0xb11:
return "SA1110";
case 0xc12:
return "IPX1200";
default:
return NULL;
}
}
static const char* fujitsuPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x001: return "A64FX";
case 0x003: return "MONAKA";
default: return NULL;
static const char* fujitsuPartId2name(uint32_t partId) {
switch (partId) {
case 0x001:
return "A64FX";
case 0x003:
return "MONAKA";
default:
return NULL;
}
}
static const char* hisiPartId2name(uint32_t partId)
{
switch (partId)
{
case 0xd01: return "TaiShan-v110"; /* used in Kunpeng-920 SoC */
case 0xd02: return "TaiShan-v120"; /* used in Kirin 990A and 9000S SoCs */
case 0xd40: return "Cortex-A76"; /* HiSilicon uses this ID though advertises A76 */
case 0xd41: return "Cortex-A77"; /* HiSilicon uses this ID though advertises A77 */
default: return NULL;
static const char* hisiPartId2name(uint32_t partId) {
switch (partId) {
case 0xd01:
return "TaiShan-v110"; /* used in Kunpeng-920 SoC */
case 0xd02:
return "TaiShan-v120"; /* used in Kirin 990A and 9000S SoCs */
case 0xd40:
return "Cortex-A76"; /* HiSilicon uses this ID though advertises A76 */
case 0xd41:
return "Cortex-A77"; /* HiSilicon uses this ID though advertises A77 */
default:
return NULL;
}
}
static const char* amperePartId2name(uint32_t partId)
{
switch (partId)
{
case 0xac3: return "Ampere-1";
case 0xac4: return "Ampere-1a";
default: return NULL;
static const char* amperePartId2name(uint32_t partId) {
switch (partId) {
case 0xac3:
return "Ampere-1";
case 0xac4:
return "Ampere-1a";
default:
return NULL;
}
}
static const char* ftPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x303: return "FTC310";
case 0x660: return "FTC660";
case 0x661: return "FTC661";
case 0x662: return "FTC662";
case 0x663: return "FTC663";
case 0x664: return "FTC664";
case 0x862: return "FTC862";
default: return NULL;
static const char* ftPartId2name(uint32_t partId) {
switch (partId) {
case 0x303:
return "FTC310";
case 0x660:
return "FTC660";
case 0x661:
return "FTC661";
case 0x662:
return "FTC662";
case 0x663:
return "FTC663";
case 0x664:
return "FTC664";
case 0x862:
return "FTC862";
default:
return NULL;
}
}
static const char* msPartId2name(uint32_t partId)
{
switch (partId)
{
case 0xd49: return "Azure-Cobalt-100";
default: return NULL;
static const char* msPartId2name(uint32_t partId) {
switch (partId) {
case 0xd49:
return "Azure-Cobalt-100";
default:
return NULL;
}
}
+32 -29
View File
@@ -4,28 +4,25 @@
#include <sys/param.h>
#if __has_include(<sys/cpuset.h>)
#include <sys/cpuset.h>
#define FF_HAVE_CPUSET 1
# include <sys/cpuset.h>
# define FF_HAVE_CPUSET 1
#endif
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
{
static const char* detectCpuTemp(const FFCPUOptions* options, double* current) {
int temp;
if (options->tempSensor.length > 0)
{
if (options->tempSensor.length > 0) {
temp = ffSysctlGetInt(options->tempSensor.chars, -999999);
if (temp == -999999)
if (temp == -999999) {
return "ffSysctlGetInt(options->tempSensor) failed";
}
else
{
}
} else {
temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
if (temp == -999999)
{
if (temp == -999999) {
// Thermal zone temperature
temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
if (temp == -999999)
if (temp == -999999) {
return "ffSysctlGetInt(\"dev.cpu.0.temperature\" or \"hw.acpi.thermal.tz0.temperature\") failed";
}
}
}
@@ -34,18 +31,17 @@ static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString("hw.model", &cpu->name) != NULL)
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
if (ffSysctlGetString("hw.model", &cpu->name) != NULL) {
return "sysctlbyname(hw.model) failed";
}
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("kern.smp.cores", 0);
cpu->coresOnline = (uint16_t) ffSysctlGetInt("kern.smp.cpus", cpu->coresLogical);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0)
{
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0) {
// <groups>
// <group level="1" cache-level="3">
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
@@ -61,8 +57,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
// </children>
// </group>
// </groups>
for (char* p = buffer.chars; (p = strstr(p, "\n </group>\n")); ++p)
for (char* p = buffer.chars; (p = strstr(p, "\n </group>\n")); ++p) {
cpu->packages++;
}
}
#if FF_HAVE_CPUSET && (__x86_64__ || __i386__)
@@ -77,28 +74,34 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffCPUDetectByCpuid(cpu);
uint32_t clockrate = (uint32_t) ffSysctlGetInt("hw.clockrate", 0);
if (clockrate > cpu->frequencyBase) cpu->frequencyBase = clockrate;
if (clockrate > cpu->frequencyBase) {
cpu->frequencyBase = clockrate;
}
for (uint16_t i = 0; i < cpu->coresLogical; ++i)
{
for (uint16_t i = 0; i < cpu->coresLogical; ++i) {
ffStrbufClear(&buffer);
char key[32];
snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i);
if (ffSysctlGetString(key, &buffer) == NULL)
{
if (buffer.length == 0) continue;
if (ffSysctlGetString(key, &buffer) == NULL) {
if (buffer.length == 0) {
continue;
}
// MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000
uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10);
if (cpu->frequencyMax < fmax) cpu->frequencyMax = fmax;
}
else
if (cpu->frequencyMax < fmax) {
cpu->frequencyMax = fmax;
}
} else {
break;
}
}
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp) detectCpuTemp(options, &cpu->temperature);
if (options->temp) {
detectCpuTemp(options, &cpu->temperature);
}
cpu->numaNodes = (uint16_t) ffSysctlGetInt("vm.ndomains", 0);
+15 -11
View File
@@ -4,28 +4,29 @@
#include <OS.h>
#include <private/shared/cpu_type.h>
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu)
{
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu) {
system_info sysInfo;
if (get_system_info(&sysInfo) != B_OK)
if (get_system_info(&sysInfo) != B_OK) {
return "get_system_info() failed";
}
uint32 topoNodeCount = 0;
get_cpu_topology_info(NULL, &topoNodeCount);
if (topoNodeCount == 0)
if (topoNodeCount == 0) {
return "get_cpu_topology_info(NULL) failed";
}
FF_AUTO_FREE cpu_topology_node_info* topology = malloc(sizeof(*topology) * topoNodeCount);
if (get_cpu_topology_info(topology, &topoNodeCount) != B_OK)
if (get_cpu_topology_info(topology, &topoNodeCount) != B_OK) {
return "get_cpu_topology_info(topology) failed";
}
enum cpu_platform platform = B_CPU_UNKNOWN;
enum cpu_vendor cpuVendor = B_CPU_VENDOR_UNKNOWN;
uint32 cpuModel = 0, frequency = 0;
uint16_t packages = 0, cores = 0;
for (uint32 i = 0; i < topoNodeCount; i++)
{
for (uint32 i = 0; i < topoNodeCount; i++) {
switch (topology[i].type) {
case B_TOPOLOGY_ROOT:
platform = topology[i].data.root.platform;
@@ -48,15 +49,18 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
}
}
const char *model = get_cpu_model_string(platform, cpuVendor, cpuModel);
if (model)
const char* model = get_cpu_model_string(platform, cpuVendor, cpuModel);
if (model) {
ffStrbufSetS(&cpu->name, model);
else
} else {
ffStrbufSetF(&cpu->name, "(Unknown %" B_PRIx32 ")", cpuModel);
}
ffStrbufSetS(&cpu->vendor, get_cpu_vendor_string(cpuVendor));
ffCPUDetectByCpuid(cpu);
if (cpu->frequencyBase < frequency) cpu->frequencyBase = frequency;
if (cpu->frequencyBase < frequency) {
cpu->frequencyBase = frequency;
}
cpu->packages = packages;
cpu->coresPhysical = cores;
cpu->coresOnline = cpu->coresLogical = (uint16_t) sysInfo.cpu_count;
File diff suppressed because it is too large Load Diff
+49 -29
View File
@@ -9,66 +9,78 @@
#include <unistd.h>
#include <fcntl.h>
static void freePropDict(prop_dictionary_t* pdict)
{
static void freePropDict(prop_dictionary_t* pdict) {
assert(pdict != NULL);
if (*pdict == NULL) return;
if (*pdict == NULL) {
return;
}
prop_object_release(*pdict);
}
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
{
static const char* detectCpuTemp(const FFCPUOptions* options, double* current) {
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
if (fd < 0) {
return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
}
__attribute__((__cleanup__(freePropDict))) prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0) {
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
}
prop_array_t array;
if (options->tempSensor.length > 0)
{
if (options->tempSensor.length > 0) {
array = prop_dictionary_get(root, options->tempSensor.chars);
if (!array) return "No temp data found in specified sensor";
}
else
{
if (!array) {
return "No temp data found in specified sensor";
}
} else {
array = prop_dictionary_get(root, "coretemp0");
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
if (!array) array = prop_dictionary_get(root, "viac7temp0");
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
if (!array) return "No temp data found in root dictionary";
if (!array) {
array = prop_dictionary_get(root, "amdzentemp0");
}
if (!array) {
array = prop_dictionary_get(root, "viac7temp0");
}
if (!array) {
array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
}
if (!array) {
return "No temp data found in root dictionary";
}
}
if (prop_array_count(array) != 2)
if (prop_array_count(array) != 2) {
return "Unexpected `xtemp0` data";
}
prop_dictionary_t dict = prop_array_get(array, 0);
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY) {
return "Unexpected `xtemp0[0]`";
}
int temp = 0; // in µK
if (!prop_dictionary_get_int(dict, "cur-value", &temp))
if (!prop_dictionary_get_int(dict, "cur-value", &temp)) {
return "Failed to get temperature";
}
*current = temp / 1e6 - 273.15;
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
if (ffSysctlGetString("machdep.cpu_brand", &cpu->name) != NULL &&
ffSysctlGetString("machdep.dmi.processor-version", &cpu->name) != NULL &&
ffSysctlGetString("hw.cpu0.name", &cpu->name) != NULL &&
ffSysctlGetString("hw.model", &cpu->name) != NULL)
{
ffSysctlGetString("hw.model", &cpu->name) != NULL) {
ffStrbufSetS(&cpu->name, "Unknown CPU");
}
if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == NULL)
if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == NULL) {
ffStrbufTrimRightSpace(&cpu->vendor);
}
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresLogical = cpu->coresPhysical;
@@ -77,13 +89,21 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffCPUDetectByCpuid(cpu);
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
if (freq == 0) freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
if (freq == 0) freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
if (freq > cpu->frequencyBase) cpu->frequencyBase = freq;
if (freq == 0) {
freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
}
if (freq == 0) {
freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
}
if (freq > cpu->frequencyBase) {
cpu->frequencyBase = freq;
}
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp) detectCpuTemp(options, &cpu->temperature);
if (options->temp) {
detectCpuTemp(options, &cpu->temperature);
}
return NULL;
}
+1 -2
View File
@@ -1,6 +1,5 @@
#include "cpu.h"
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FF_MAYBE_UNUSED FFCPUResult* cpu)
{
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FF_MAYBE_UNUSED FFCPUResult* cpu) {
return "Not supported on this platform";
}
+36 -34
View File
@@ -6,48 +6,46 @@
#include <sys/time.h>
#include <sys/sensors.h>
static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu)
{
static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu) {
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
for (mib[2] = 0; mib[2] < 1024; mib[2]++)
{
for (mib[2] = 0; mib[2] < 1024; mib[2]++) {
struct sensordev sensordev;
size_t sdlen = sizeof(struct sensordev);
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) < 0)
{
if (errno == ENOENT)
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) < 0) {
if (errno == ENOENT) {
break;
if (errno == ENXIO)
}
if (errno == ENXIO) {
continue;
}
return "sysctl(sensordev) failed";
}
if (options->tempSensor.length > 0)
{
if (!ffStrbufEqualS(&options->tempSensor, sensordev.xname))
continue;
}
else
{
if (!ffStrStartsWith(sensordev.xname, "cpu"))
continue;
}
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
{
struct sensor sensor;
size_t slen = sizeof(struct sensor);
if (sysctl(mib, 5, &sensor, &slen, NULL, 0) < 0)
{
if (errno != ENOENT)
return "sysctl(sensor) failed";
if (options->tempSensor.length > 0) {
if (!ffStrbufEqualS(&options->tempSensor, sensordev.xname)) {
continue;
}
if (sensor.flags & SENSOR_FINVALID)
} else {
if (!ffStrStartsWith(sensordev.xname, "cpu")) {
continue;
}
}
cpu->temperature = (double)(sensor.value - 273150000) / 1E6;
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++) {
struct sensor sensor;
size_t slen = sizeof(struct sensor);
if (sysctl(mib, 5, &sensor, &slen, NULL, 0) < 0) {
if (errno != ENOENT) {
return "sysctl(sensor) failed";
}
continue;
}
if (sensor.flags & SENSOR_FINVALID) {
continue;
}
cpu->temperature = (double) (sensor.value - 273150000) / 1E6;
return NULL;
}
}
@@ -55,10 +53,10 @@ static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu)
return "No sensor for CPU temp found";
}
const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name))
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name)) {
return "sysctl(hw.model) failed";
}
cpu->coresPhysical = (uint16_t) ffSysctlGetInt(CTL_HW, HW_NCPU, 1);
cpu->coresLogical = cpu->coresPhysical;
@@ -67,10 +65,14 @@ const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffCPUDetectByCpuid(cpu);
uint32_t cpuspeed = (uint32_t) ffSysctlGetInt(CTL_HW, HW_CPUSPEED, 0);
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
if (cpuspeed > cpu->frequencyBase) {
cpu->frequencyBase = cpuspeed;
}
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp) detectCPUTemp(options, cpu);
if (options->temp) {
detectCPUTemp(options, cpu);
}
return NULL;
}
+48 -48
View File
@@ -3,8 +3,7 @@
#include "common/stringUtils.h"
#include <kstat.h>
static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t* kc, FFCPUResult* cpu)
{
static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t* kc, FFCPUResult* cpu) {
const char* possibleModules[] = {"temperature", "cpu_temp", "acpi_thermal", NULL};
if (options->tempSensor.length > 0) {
@@ -19,10 +18,10 @@ static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t
if (kn) {
switch (kn->data_type) {
case KSTAT_DATA_INT32:
cpu->temperature = (float)kn->value.i32;
cpu->temperature = (float) kn->value.i32;
return NULL;
case KSTAT_DATA_UINT32:
cpu->temperature = (float)kn->value.ui32;
cpu->temperature = (float) kn->value.ui32;
return NULL;
case KSTAT_DATA_FLOAT:
cpu->temperature = kn->value.f;
@@ -35,61 +34,53 @@ static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t
return "Failed to find CPU temperature using kstat";
}
static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu)
{
static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]){
"ipmitool",
"-c",
"sdr",
"list",
NULL
});
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) {"ipmitool", "-c", "sdr", "list", NULL});
if (error)
if (error) {
return error;
}
char* line = NULL;
size_t len = 0;
while (ffStrbufGetline(&line, &len, &buffer))
{
if (sscanf(line, "CPU%*d Temp,%lf,degrees C,ok", &cpu->temperature) == 1)
while (ffStrbufGetline(&line, &len, &buffer)) {
if (sscanf(line, "CPU%*d Temp,%lf,degrees C,ok", &cpu->temperature) == 1) {
return NULL;
}
}
return "ipmitool sdr list failed to find CPU temperature";
}
static inline void kstatFreeWrap(kstat_ctl_t** pkc)
{
static inline void kstatFreeWrap(kstat_ctl_t** pkc) {
assert(pkc);
if (*pkc)
if (*pkc) {
kstat_close(*pkc);
}
}
static inline uint16_t countTypeId(kstat_ctl_t* kc, const char* type)
{
static inline uint16_t countTypeId(kstat_ctl_t* kc, const char* type) {
uint64_t low = 0, high = 0;
for (kstat_t* ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
{
if (ffStrStartsWith(ksp->ks_module, "cpu_info"))
{
if (kstat_read(kc, ksp, NULL) < 0)
for (kstat_t* ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
if (ffStrStartsWith(ksp->ks_module, "cpu_info")) {
if (kstat_read(kc, ksp, NULL) < 0) {
continue;
}
kstat_named_t* stat = kstat_data_lookup(ksp, type);
if (!stat)
if (!stat) {
continue;
}
uint32_t id = 0;
switch (stat->data_type)
{
#ifdef _INT64_TYPE
switch (stat->data_type) {
#ifdef _INT64_TYPE
case KSTAT_DATA_INT64:
case KSTAT_DATA_UINT64:
id = (uint32_t) stat->value.ui64;
break;
#endif
#endif
case KSTAT_DATA_INT32:
case KSTAT_DATA_UINT32:
id = stat->value.ui32;
@@ -97,57 +88,66 @@ static inline uint16_t countTypeId(kstat_ctl_t* kc, const char* type)
default:
continue;
}
if (__builtin_expect(id > 64, false))
if (__builtin_expect(id > 64, false)) {
high |= 1ULL << (id - 64);
else
} else {
low |= 1ULL << id;
}
}
}
return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high));
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
__attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open();
if (!kc)
if (!kc) {
return "kstat_open() failed";
}
kstat_t* ks = kstat_lookup(kc, "cpu_info", -1, NULL);
if (!ks)
if (!ks) {
return "kstat_lookup() failed";
}
if (kstat_read(kc, ks, NULL) < 0)
if (kstat_read(kc, ks, NULL) < 0) {
return "kstat_read() failed";
}
{
kstat_named_t* kn = kstat_data_lookup(ks, "brand");
if (kn) ffStrbufSetNS(&cpu->name, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
if (kn) {
ffStrbufSetNS(&cpu->name, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
}
}
{
kstat_named_t* kn = kstat_data_lookup(ks, "vendor_id");
if (kn) ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
if (kn) {
ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
}
}
ffCPUDetectByCpuid(cpu);
{
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
if (kn && kn->value.ui32 > cpu->frequencyBase)
if (kn && kn->value.ui32 > cpu->frequencyBase) {
cpu->frequencyBase = kn->value.ui32;
}
}
ks = kstat_lookup(kc, "unix", -1, "system_misc");
if (ks && kstat_read(kc, ks, NULL) >= 0)
{
if (ks && kstat_read(kc, ks, NULL) >= 0) {
kstat_named_t* kn = kstat_data_lookup(ks, "ncpus");
if (kn) cpu->coresLogical = cpu->coresOnline = (uint16_t) kn->value.ui32;
if (kn) {
cpu->coresLogical = cpu->coresOnline = (uint16_t) kn->value.ui32;
}
}
cpu->packages = countTypeId(kc, "chip_id");
cpu->coresPhysical = countTypeId(kc, "core_id");
if (options->temp)
{
if (detectCPUTempByKstat(options, kc, cpu) != NULL)
if (options->temp) {
if (detectCPUTempByKstat(options, kc, cpu) != NULL) {
detectCPUTempByIpmiTool(cpu);
}
}
return NULL;
+135 -123
View File
@@ -9,26 +9,22 @@
#include "common/windows/nt.h"
#include <wchar.h>
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
{
if (*phQuery != NULL)
{
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery) {
if (*phQuery != NULL) {
PerfCloseQueryHandle(*phQuery);
*phQuery = NULL;
}
}
const char* detectThermalTemp(const FFCPUOptions* options, double* result)
{
struct FFPerfQuerySpec
{
const char* detectThermalTemp(const FFCPUOptions* options, double* result) {
struct FFPerfQuerySpec {
PERF_COUNTER_IDENTIFIER Identifier;
WCHAR Name[16];
} querySpec = {
.Identifier = {
// Thermal Zone Information
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{52bc5412-dac2-449c-8bc2-96443888fe6b}
.CounterSetGuid = { 0x52bc5412, 0xdac2, 0x449c, {0x8b, 0xc2, 0x96, 0x44, 0x38, 0x88, 0xfe, 0x6b} },
.CounterSetGuid = {0x52bc5412, 0xdac2, 0x449c, {0x8b, 0xc2, 0x96, 0x44, 0x38, 0x88, 0xfe, 0x6b}},
.Size = sizeof(querySpec),
.CounterId = PERF_WILDCARD_COUNTER,
.InstanceId = PERF_WILDCARD_COUNTER,
@@ -36,43 +32,47 @@ const char* detectThermalTemp(const FFCPUOptions* options, double* result)
.Name = L"\\_TZ.CPUZ", // The standard(?) instance name for CPU temperature in the thermal provider
};
if (options->tempSensor.length > 0)
{
if (!NT_SUCCESS(RtlUTF8ToUnicodeN(querySpec.Name, (ULONG) sizeof(querySpec.Name), NULL, options->tempSensor.chars, (ULONG)options->tempSensor.length + 1)))
if (options->tempSensor.length > 0) {
if (!NT_SUCCESS(RtlUTF8ToUnicodeN(querySpec.Name, (ULONG) sizeof(querySpec.Name), NULL, options->tempSensor.chars, (ULONG) options->tempSensor.length + 1))) {
return "Invalid temp sensor string";
}
}
DWORD dataSize = 0;
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY) {
return "PerfEnumerateCounterSetInstances() failed";
}
if (dataSize <= sizeof(PERF_INSTANCE_HEADER))
if (dataSize <= sizeof(PERF_INSTANCE_HEADER)) {
return "No `Thermal Zone Information` instances found";
}
{
FF_AUTO_FREE PERF_INSTANCE_HEADER* const pHead = malloc(dataSize);
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, pHead, dataSize, &dataSize) != ERROR_SUCCESS)
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, pHead, dataSize, &dataSize) != ERROR_SUCCESS) {
return "PerfEnumerateCounterSetInstances() failed to get instance headers";
PERF_INSTANCE_HEADER* pInstanceHeader = pHead;
while (1)
{
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pInstanceHeader + sizeof(*pInstanceHeader));
if (wcscmp(instanceName, querySpec.Name) == 0)
break;
dataSize -= pInstanceHeader->Size;
if (dataSize == 0)
break;
pInstanceHeader = (PERF_INSTANCE_HEADER*)((BYTE*)pInstanceHeader + pInstanceHeader->Size);
}
if (dataSize == 0)
{
if (options->tempSensor.length > 0)
return "Unable to find CPU sensor";
PERF_INSTANCE_HEADER* pInstanceHeader = pHead;
while (1) {
const wchar_t* instanceName = (const wchar_t*) ((BYTE*) pInstanceHeader + sizeof(*pInstanceHeader));
if (wcscmp(instanceName, querySpec.Name) == 0) {
break;
}
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pHead + sizeof(*pHead));
dataSize -= pInstanceHeader->Size;
if (dataSize == 0) {
break;
}
pInstanceHeader = (PERF_INSTANCE_HEADER*) ((BYTE*) pInstanceHeader + pInstanceHeader->Size);
}
if (dataSize == 0) {
if (options->tempSensor.length > 0) {
return "Unable to find CPU sensor";
}
const wchar_t* instanceName = (const wchar_t*) ((BYTE*) pHead + sizeof(*pHead));
wcscpy(querySpec.Name, instanceName); // Use the first instance name if the specific one is not found
}
}
@@ -80,75 +80,80 @@ const char* detectThermalTemp(const FFCPUOptions* options, double* result)
__attribute__((__cleanup__(ffPerfCloseQueryHandle)))
HANDLE hQuery = NULL;
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS) {
return "PerfOpenQueryHandle() failed";
}
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS) {
return "PerfAddCounters() failed";
}
if (querySpec.Identifier.Status != ERROR_SUCCESS)
if (querySpec.Identifier.Status != ERROR_SUCCESS) {
return "PerfAddCounters() reports invalid identifier";
}
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY) {
return "PerfQueryCounterData(NULL) failed";
}
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER)) // PERF_ERROR_RETURN, should not happen
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER)) { // PERF_ERROR_RETURN, should not happen
return "instance doesn't exist";
}
FF_AUTO_FREE PERF_DATA_HEADER* const pDataHeader = malloc(dataSize);
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS)
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS) {
return "PerfQueryCounterData(pDataHeader) failed";
}
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*)(pDataHeader + 1);
if (pCounterHeader->dwType != PERF_MULTIPLE_COUNTERS)
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*) (pDataHeader + 1);
if (pCounterHeader->dwType != PERF_MULTIPLE_COUNTERS) {
return "Invalid counter type";
}
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*)(pCounterHeader + 1);
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pMultiCounters + pMultiCounters->dwSize);
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*) (pCounterHeader + 1);
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*) ((BYTE*) pMultiCounters + pMultiCounters->dwSize);
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++)
{
if (pCounterData->dwDataSize == sizeof(int32_t))
{
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
int32_t value = *(int32_t*)(pCounterData + 1);
if (value == 0)
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++) {
if (pCounterData->dwDataSize == sizeof(int32_t)) {
DWORD* pCounterIds = (DWORD*) (pMultiCounters + 1);
int32_t value = *(int32_t*) (pCounterData + 1);
if (value == 0) {
return "Temperature data is zero";
}
switch (pCounterIds[iCounter]) {
case 0: // Temperature
*result = value - 273;
break;
case 3: // High Precision Temperature
*result = value / 10.0 - 273;
break;
case 0: // Temperature
*result = value - 273;
break;
case 3: // High Precision Temperature
*result = value / 10.0 - 273;
break;
}
}
pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pCounterData + pCounterData->dwSize);
pCounterData = (PERF_COUNTER_DATA*) ((BYTE*) pCounterData + pCounterData->dwSize);
}
return NULL;
}
// 7.5
typedef struct FFSmbiosProcessorInfo
{
typedef struct FFSmbiosProcessorInfo {
FFSmbiosHeader Header;
uint8_t SocketDesignation; // string
uint8_t ProcessorType; // enum
uint8_t ProcessorFamily; // enum
uint8_t SocketDesignation; // string
uint8_t ProcessorType; // enum
uint8_t ProcessorFamily; // enum
uint8_t ProcessorManufacturer; // string
uint64_t ProcessorID; // varies
uint8_t ProcessorVersion; // string
uint8_t Voltage; // varies
uint16_t ExternalClock; // varies
uint16_t MaxSpeed; // varies
uint16_t CurrentSpeed; // varies
uint8_t Status; // varies
uint8_t ProcessorUpgrade; // enum
uint64_t ProcessorID; // varies
uint8_t ProcessorVersion; // string
uint8_t Voltage; // varies
uint16_t ExternalClock; // varies
uint16_t MaxSpeed; // varies
uint16_t CurrentSpeed; // varies
uint8_t Status; // varies
uint8_t ProcessorUpgrade; // enum
// 2.1+
uint16_t L1CacheHandle; // varies
@@ -157,20 +162,20 @@ typedef struct FFSmbiosProcessorInfo
// 2.3+
uint8_t SerialNumber; // string
uint8_t AssertTag; // string
uint8_t PartNumber; // string
uint8_t AssertTag; // string
uint8_t PartNumber; // string
// 2.5+
uint8_t CoreCount; // varies
uint8_t CoreEnabled; // varies
uint8_t ThreadCount; // varies
uint8_t CoreCount; // varies
uint8_t CoreEnabled; // varies
uint8_t ThreadCount; // varies
uint16_t ProcessorCharacteristics; // bit field
// 2.6+
uint16_t ProcessorFamily2; // enum
// 3.0+
uint16_t CoreCount2; // varies
uint16_t CoreCount2; // varies
uint16_t CoreEnabled2; // varies
uint16_t ThreadCount2; // varies
@@ -181,128 +186,135 @@ typedef struct FFSmbiosProcessorInfo
static_assert(offsetof(FFSmbiosProcessorInfo, ThreadEnabled) == 0x30,
"FFSmbiosProcessorInfo: Wrong struct alignment");
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
{
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu) {
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
if (!smbiosTable)
if (!smbiosTable) {
return "Failed to get SMBIOS data";
}
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_PROCESSOR_INFO];
if (!data)
if (!data) {
return "Processor information is not found in SMBIOS data";
}
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/)
{
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/) {
data = (const FFSmbiosProcessorInfo*) ffSmbiosNextEntry(&data->Header);
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO)
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO) {
return "No active CPU is found in SMBIOS data";
}
}
uint32_t speed = data->MaxSpeed;
// Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2)
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2) {
return "Possible invalid CPU max speed in SMBIOS data. See #800";
}
cpu->frequencyMax = speed;
return NULL;
}
static const char* detectNCores(FFCPUResult* cpu)
{
static const char* detectNCores(FFCPUResult* cpu) {
LOGICAL_PROCESSOR_RELATIONSHIP lpr = RelationAll;
ULONG length = 0;
NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), NULL, 0, &length);
if (length == 0)
if (length == 0) {
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
}
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) malloc(length);
if (!NT_SUCCESS(NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), pProcessorInfo, length, &length)))
if (!NT_SUCCESS(NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), pProcessorInfo, length, &length))) {
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
}
for(
for (
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
)
{
if (ptr->Relationship == RelationGroup)
{
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index)
{
(uint8_t*) ptr < ((uint8_t*) pProcessorInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) (((uint8_t*) ptr) + ptr->Size)) {
if (ptr->Relationship == RelationGroup) {
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index) {
cpu->coresOnline += ptr->Group.GroupInfo[index].ActiveProcessorCount;
cpu->coresLogical += ptr->Group.GroupInfo[index].MaximumProcessorCount;
}
}
else if (ptr->Relationship == RelationProcessorCore)
} else if (ptr->Relationship == RelationProcessorCore) {
++cpu->coresPhysical;
else if (ptr->Relationship == RelationProcessorPackage)
} else if (ptr->Relationship == RelationProcessorPackage) {
++cpu->packages;
else if (ptr->Relationship == RelationNumaNode)
} else if (ptr->Relationship == RelationNumaNode) {
++cpu->numaNodes;
}
}
return NULL;
}
static const char* detectByRegistry(FFCPUResult* cpu)
{
static const char* detectByRegistry(FFCPUResult* cpu) {
FF_AUTO_CLOSE_FD HANDLE hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL)) {
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
}
if (ffRegReadValues(hKey, 3, (FFRegValueArg[]) {
FF_ARG(cpu->name, L"ProcessorNameString"),
FF_ARG(cpu->vendor, L"VendorIdentifier"),
FF_ARG(cpu->frequencyBase, L"~MHz"),
}, NULL))
FF_ARG(cpu->name, L"ProcessorNameString"),
FF_ARG(cpu->vendor, L"VendorIdentifier"),
FF_ARG(cpu->frequencyBase, L"~MHz"),
},
NULL)) {
ffStrbufTrimRightSpace(&cpu->vendor);
else
} else {
return "ffRegReadValues() failed for CPU registry key";
}
return NULL;
}
static const char* detectCoreTypes(FFCPUResult* cpu)
{
static const char* detectCoreTypes(FFCPUResult* cpu) {
FF_AUTO_FREE PROCESSOR_POWER_INFORMATION* pinfo = calloc(cpu->coresLogical, sizeof(PROCESSOR_POWER_INFORMATION));
if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical)))
if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical))) {
return "NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, size) failed";
}
for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore)
{
for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore) {
uint32_t ifreq = 0;
while (cpu->coreTypes[ifreq].freq != pinfo[icore].MhzLimit && cpu->coreTypes[ifreq].freq > 0)
while (cpu->coreTypes[ifreq].freq != pinfo[icore].MhzLimit && cpu->coreTypes[ifreq].freq > 0) {
++ifreq;
if (cpu->coreTypes[ifreq].freq == 0)
}
if (cpu->coreTypes[ifreq].freq == 0) {
cpu->coreTypes[ifreq].freq = pinfo[icore].MhzLimit;
}
++cpu->coreTypes[ifreq].count;
}
if (cpu->frequencyBase == 0)
if (cpu->frequencyBase == 0) {
cpu->frequencyBase = pinfo->MaxMhz;
}
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
detectNCores(cpu);
const char* error = detectByRegistry(cpu);
if (error)
if (error) {
return error;
}
ffCPUDetectByCpuid(cpu);
if (options->showPeCoreCount) detectCoreTypes(cpu);
if (options->showPeCoreCount) {
detectCoreTypes(cpu);
}
if (cpu->frequencyMax == 0)
if (cpu->frequencyMax == 0) {
detectMaxSpeedBySmbios(cpu);
}
if(options->temp)
if (options->temp) {
detectThermalTemp(options, &cpu->temperature);
}
return NULL;
}
+7 -13
View File
@@ -3,43 +3,37 @@
#include "fastfetch.h"
#include "modules/cpucache/option.h"
typedef enum __attribute__((__packed__)) FFCPUCacheType
{
typedef enum __attribute__((__packed__)) FFCPUCacheType {
FF_CPU_CACHE_TYPE_UNIFIED = 0,
FF_CPU_CACHE_TYPE_INSTRUCTION = 1,
FF_CPU_CACHE_TYPE_DATA = 2,
FF_CPU_CACHE_TYPE_TRACE = 3,
} FFCPUCacheType;
typedef struct FFCPUCache
{
typedef struct FFCPUCache {
uint32_t size;
uint32_t num;
uint32_t lineSize;
FFCPUCacheType type;
} FFCPUCache;
typedef struct FFCPUCacheResult
{
typedef struct FFCPUCacheResult {
FFlist caches[4]; // L1, L2, L3, L4(?)
} FFCPUCacheResult;
const char* ffDetectCPUCache(FFCPUCacheResult* result);
static inline FFCPUCache* ffCPUCacheAddItem(FFCPUCacheResult* result, uint32_t level, uint32_t size, uint32_t lineSize, FFCPUCacheType type)
{
static inline FFCPUCache* ffCPUCacheAddItem(FFCPUCacheResult* result, uint32_t level, uint32_t size, uint32_t lineSize, FFCPUCacheType type) {
FFlist* cacheLevel = &result->caches[level - 1];
FF_LIST_FOR_EACH(FFCPUCache, item, *cacheLevel)
{
if (item->type == type && item->size == size && item->lineSize == lineSize)
{
FF_LIST_FOR_EACH (FFCPUCache, item, *cacheLevel) {
if (item->type == type && item->size == size && item->lineSize == lineSize) {
item->num++;
return item;
}
}
FFCPUCache* item = (FFCPUCache*)ffListAdd(cacheLevel);
FFCPUCache* item = (FFCPUCache*) ffListAdd(cacheLevel);
*item = (FFCPUCache) {
.size = size,
.num = 1,
+18 -14
View File
@@ -2,11 +2,12 @@
#include "common/sysctl.h"
#include "common/stringUtils.h"
const char* ffDetectCPUCache(FFCPUCacheResult* result)
{
const char* ffDetectCPUCache(FFCPUCacheResult* result) {
// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_system_capabilities#3901385
uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0);
if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed";
if (nPerfLevels <= 0) {
return "sysctl(hw.nperflevels) failed";
}
// macOS provides the global system cache line size
uint32_t lineSize = (uint32_t) ffSysctlGetInt64("hw.cachelinesize", 0);
@@ -16,42 +17,45 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result)
char* pSubkey = sysctlKey + strlen("hw.perflevelN.");
const size_t lenLeft = ARRAY_SIZE(sysctlKey) - strlen("hw.perflevelN.");
for (uint32_t i = 0; i < nPerfLevels; ++i)
{
for (uint32_t i = 0; i < nPerfLevels; ++i) {
*pNum = (char) ('0' + i);
ffStrCopy(pSubkey, "physicalcpu", lenLeft);
uint32_t ncpu = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (ncpu <= 0) continue;
if (ncpu <= 0) {
continue;
}
ffStrCopy(pSubkey, "l1icachesize", lenLeft);
uint32_t size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
if (size) {
ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_INSTRUCTION)->num = ncpu;
}
ffStrCopy(pSubkey, "l1dcachesize", lenLeft);
size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
if (size) {
ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_DATA)->num = ncpu;
}
ffStrCopy(pSubkey, "l2cachesize", lenLeft);
size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
{
if (size) {
ffStrCopy(pSubkey, "cpusperl2", lenLeft);
uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (cpuSper)
if (cpuSper) {
ffCPUCacheAddItem(result, 2, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
}
}
ffStrCopy(pSubkey, "l3cachesize", lenLeft);
size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
{
if (size) {
ffStrCopy(pSubkey, "cpusperl3", lenLeft);
uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (cpuSper)
if (cpuSper) {
ffCPUCacheAddItem(result, 3, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
}
}
}
+55 -32
View File
@@ -2,107 +2,130 @@
#include "common/io.h"
#include "common/stringUtils.h"
static const char* parseCpuCacheIndex(FFstrbuf* path, FFCPUCacheResult* result, FFstrbuf* buffer, FFstrbuf* added)
{
static const char* parseCpuCacheIndex(FFstrbuf* path, FFCPUCacheResult* result, FFstrbuf* buffer, FFstrbuf* added) {
uint32_t baseLen = path->length;
ffStrbufAppendS(path, "/level");
if (!ffReadFileBuffer(path->chars, buffer))
if (!ffReadFileBuffer(path->chars, buffer)) {
return "ffReadFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/level\") == NULL";
}
uint32_t level = (uint32_t) ffStrbufToUInt(buffer, 0);
if (level < 1 || level > 4) return "level < 1 || level > 4";
if (level < 1 || level > 4) {
return "level < 1 || level > 4";
}
ffStrbufSubstrBefore(path, baseLen);
ffStrbufAppendS(path, "/size");
if (!ffReadFileBuffer(path->chars, buffer))
if (!ffReadFileBuffer(path->chars, buffer)) {
return "ffReadFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/size\") == NULL";
}
uint32_t sizeKb = (uint32_t) ffStrbufToUInt(buffer, 0);
if (sizeKb == 0) return "size == 0";
if (sizeKb == 0) {
return "size == 0";
}
ffStrbufSubstrBefore(path, baseLen);
ffStrbufAppendS(path, "/type");
if (!ffReadFileBuffer(path->chars, buffer))
if (!ffReadFileBuffer(path->chars, buffer)) {
return "ffReadFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/type\") == NULL";
}
ffStrbufTrimRightSpace(buffer);
FFCPUCacheType cacheType = 0;
switch (buffer->chars[0])
{
case 'I': cacheType = FF_CPU_CACHE_TYPE_INSTRUCTION; break;
case 'D': cacheType = FF_CPU_CACHE_TYPE_DATA; break;
case 'U': cacheType = FF_CPU_CACHE_TYPE_UNIFIED; break;
case 'T': cacheType = FF_CPU_CACHE_TYPE_TRACE; break;
default: return "unknown cache type";
switch (buffer->chars[0]) {
case 'I':
cacheType = FF_CPU_CACHE_TYPE_INSTRUCTION;
break;
case 'D':
cacheType = FF_CPU_CACHE_TYPE_DATA;
break;
case 'U':
cacheType = FF_CPU_CACHE_TYPE_UNIFIED;
break;
case 'T':
cacheType = FF_CPU_CACHE_TYPE_TRACE;
break;
default:
return "unknown cache type";
}
uint32_t lineSize = 0;
ffStrbufSubstrBefore(path, baseLen);
ffStrbufAppendS(path, "/coherency_line_size");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBuffer(path->chars, buffer)) {
lineSize = (uint32_t) ffStrbufToUInt(buffer, 0);
}
ffStrbufSubstrBefore(path, baseLen);
ffStrbufAppendS(path, "/shared_cpu_list");
ffStrbufClear(buffer);
ffStrbufAppendC(buffer, '[');
if (!ffAppendFileBuffer(path->chars, buffer))
if (!ffAppendFileBuffer(path->chars, buffer)) {
return "ffAppendFileBuffer(\"/sys/devices/system/cpu/cpuX/cache/indexX/shared_cpu_list\") == NULL";
}
ffStrbufTrimRightSpace(buffer);
// deduplicate shared caches
ffStrbufAppendF(buffer, "_%u_%u_%u_%u]", level, sizeKb, lineSize, cacheType);
if (ffStrbufContain(added, buffer)) return NULL;
if (ffStrbufContain(added, buffer)) {
return NULL;
}
ffStrbufAppend(added, buffer);
ffCPUCacheAddItem(result, level, sizeKb * 1024, lineSize, cacheType);
return NULL;
}
static const char* parseCpuCache(FFstrbuf* path, FFCPUCacheResult* result, FFstrbuf* buffer, FFstrbuf* added)
{
static const char* parseCpuCache(FFstrbuf* path, FFCPUCacheResult* result, FFstrbuf* buffer, FFstrbuf* added) {
ffStrbufAppendS(path, "/cache/");
uint32_t baseLen = path->length;
FF_AUTO_CLOSE_DIR DIR* pathCacheDir = opendir(path->chars);
if (!pathCacheDir)
if (!pathCacheDir) {
return "opendir(\"/sys/devices/system/cpu/cpuX/cache/\") == NULL";
}
struct dirent* pathCacheEntry;
while ((pathCacheEntry = readdir(pathCacheDir)) != NULL)
{
if (!ffStrStartsWith(pathCacheEntry->d_name, "index")
|| !ffCharIsDigit(pathCacheEntry->d_name[strlen("index")])) continue;
while ((pathCacheEntry = readdir(pathCacheDir)) != NULL) {
if (!ffStrStartsWith(pathCacheEntry->d_name, "index") || !ffCharIsDigit(pathCacheEntry->d_name[strlen("index")])) {
continue;
}
ffStrbufAppendS(path, pathCacheEntry->d_name);
const char* error = parseCpuCacheIndex(path, result, buffer, added);
if (error) return error;
if (error) {
return error;
}
ffStrbufSubstrBefore(path, baseLen);
}
return NULL;
}
const char* ffDetectCPUCache(FFCPUCacheResult* result)
{
const char* ffDetectCPUCache(FFCPUCacheResult* result) {
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/devices/system/cpu/");
uint32_t baseLen = path.length;
FF_AUTO_CLOSE_DIR DIR* pathCpuDir = opendir(path.chars);
if (!pathCpuDir)
if (!pathCpuDir) {
return "opendir(\"/sys/devices/system/cpu/\") == NULL";
}
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY added = ffStrbufCreate();
struct dirent* pathCpuEntry;
while ((pathCpuEntry = readdir(pathCpuDir)) != NULL)
{
while ((pathCpuEntry = readdir(pathCpuDir)) != NULL) {
if (!ffStrStartsWith(pathCpuEntry->d_name, "cpu") ||
!ffCharIsDigit(pathCpuEntry->d_name[strlen("cpu")])) continue;
!ffCharIsDigit(pathCpuEntry->d_name[strlen("cpu")])) {
continue;
}
ffStrbufAppendS(&path, pathCpuEntry->d_name);
const char* error = parseCpuCache(&path, result, &buffer, &added);
if (error) return error;
if (error) {
return error;
}
ffStrbufSubstrBefore(&path, baseLen);
}
return NULL;
+1 -2
View File
@@ -1,6 +1,5 @@
#include "cpucache.h"
const char* ffDetectCPUCache(FF_MAYBE_UNUSED FFCPUCacheResult* result)
{
const char* ffDetectCPUCache(FF_MAYBE_UNUSED FFCPUCacheResult* result) {
return "Not supported on this platform";
}
+35 -31
View File
@@ -2,61 +2,60 @@
#include "common/smbiosHelper.h"
#include "common/stringUtils.h"
typedef struct FFSmbiosCacheInfo
{
typedef struct FFSmbiosCacheInfo {
FFSmbiosHeader Header;
uint8_t SocketDesignation; // string
uint8_t SocketDesignation; // string
uint16_t CacheConfiguration; // varies
uint16_t MaximumCacheSize; // varies
uint16_t InstalledSize; // varies
uint16_t SupportedSramType; // bit field
uint16_t CurrentSramType; // bit field
uint16_t MaximumCacheSize; // varies
uint16_t InstalledSize; // varies
uint16_t SupportedSramType; // bit field
uint16_t CurrentSramType; // bit field
// 2.1+
uint8_t CacheSpeed; // varies
uint8_t CacheSpeed; // varies
uint8_t ErrorCorrectionType; // enum
uint8_t SystemCacheType; // enum
uint8_t Associativity; // enum
uint8_t SystemCacheType; // enum
uint8_t Associativity; // enum
// 3.1+
uint32_t MaximumCacheSize2; // bit field
uint32_t MaximumCacheSize2; // bit field
uint32_t InstalledCacheSize2; // bit field
} __attribute__((__packed__)) FFSmbiosCacheInfo;
static_assert(offsetof(FFSmbiosCacheInfo, InstalledCacheSize2) == 0x17,
"FFSmbiosCacheInfo: Wrong struct alignment");
const char* ffDetectCPUCache(FFCPUCacheResult* result)
{
const char* ffDetectCPUCache(FFCPUCacheResult* result) {
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
if (!smbiosTable)
if (!smbiosTable) {
return "Failed to get SMBIOS data";
}
const FFSmbiosCacheInfo* data = (const FFSmbiosCacheInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_CACHE_INFO];
if (!data)
if (!data) {
return "Cache information is not found in SMBIOS data";
}
const FFSmbiosCacheInfo* endOfTable = (const FFSmbiosCacheInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_END_OF_TABLE];
for (; data != endOfTable; data = (const FFSmbiosCacheInfo*) ffSmbiosNextEntry(&data->Header))
{
if (data->Header.Type != FF_SMBIOS_TYPE_CACHE_INFO)
for (; data != endOfTable; data = (const FFSmbiosCacheInfo*) ffSmbiosNextEntry(&data->Header)) {
if (data->Header.Type != FF_SMBIOS_TYPE_CACHE_INFO) {
continue;
}
bool enabled = !!(data->CacheConfiguration & (1 << 7));
if (!enabled)
if (!enabled) {
continue;
}
uint32_t size = data->InstalledSize;
if (size == 0)
if (size == 0) {
continue;
if (data->InstalledSize != 0xFFFF)
{
size *= (size >> 15 ? 64 : 1) * 1024u;
}
else if (data->Header.Length > offsetof(FFSmbiosCacheInfo, InstalledCacheSize2))
{
if (data->InstalledSize != 0xFFFF) {
size *= (size >> 15 ? 64 : 1) * 1024u;
} else if (data->Header.Length > offsetof(FFSmbiosCacheInfo, InstalledCacheSize2)) {
size = data->InstalledCacheSize2;
size *= (size >> 31 ? 64 : 1) * 1024u;
}
@@ -64,11 +63,16 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result)
uint32_t level = (data->CacheConfiguration & 0b111u) + 1;
FFCPUCacheType type;
switch (data->SystemCacheType)
{
case 3: type = FF_CPU_CACHE_TYPE_INSTRUCTION; break;
case 4: type = FF_CPU_CACHE_TYPE_DATA; break;
default: type = FF_CPU_CACHE_TYPE_UNIFIED; break;
switch (data->SystemCacheType) {
case 3:
type = FF_CPU_CACHE_TYPE_INSTRUCTION;
break;
case 4:
type = FF_CPU_CACHE_TYPE_DATA;
break;
default:
type = FF_CPU_CACHE_TYPE_UNIFIED;
break;
}
ffCPUCacheAddItem(result, level, size, 0, type);
+25 -19
View File
@@ -2,36 +2,42 @@
#include "common/mallocHelper.h"
#include "common/windows/nt.h"
const char* ffDetectCPUCache(FFCPUCacheResult* result)
{
const char* ffDetectCPUCache(FFCPUCacheResult* result) {
LOGICAL_PROCESSOR_RELATIONSHIP lpr = RelationCache;
DWORD length = 0;
NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), NULL, 0, &length);
if (length == 0)
if (length == 0) {
return "GetLogicalProcessorInformationEx(RelationCache, NULL, &length) failed";
}
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) malloc(length);
if (!NT_SUCCESS(NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), pProcessorInfo, length, &length)))
if (!NT_SUCCESS(NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), pProcessorInfo, length, &length))) {
return "GetLogicalProcessorInformationEx(RelationCache, pProcessorInfo, &length) failed";
}
for(
for (
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
)
{
if(__builtin_expect(ptr->Relationship == RelationCache && ptr->Cache.Level > 0 && ptr->Cache.Level <= 4, true))
{
(uint8_t*) ptr < ((uint8_t*) pProcessorInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) (((uint8_t*) ptr) + ptr->Size)) {
if (__builtin_expect(ptr->Relationship == RelationCache && ptr->Cache.Level > 0 && ptr->Cache.Level <= 4, true)) {
FFCPUCacheType cacheType = 0;
switch (ptr->Cache.Type)
{
case CacheUnified: cacheType = FF_CPU_CACHE_TYPE_UNIFIED; break;
case CacheInstruction: cacheType = FF_CPU_CACHE_TYPE_INSTRUCTION; break;
case CacheData: cacheType = FF_CPU_CACHE_TYPE_DATA; break;
case CacheTrace: cacheType = FF_CPU_CACHE_TYPE_TRACE; break;
default: break;
switch (ptr->Cache.Type) {
case CacheUnified:
cacheType = FF_CPU_CACHE_TYPE_UNIFIED;
break;
case CacheInstruction:
cacheType = FF_CPU_CACHE_TYPE_INSTRUCTION;
break;
case CacheData:
cacheType = FF_CPU_CACHE_TYPE_DATA;
break;
case CacheTrace:
cacheType = FF_CPU_CACHE_TYPE_TRACE;
break;
default:
break;
}
ffCPUCacheAddItem(result, ptr->Cache.Level, ptr->Cache.CacheSize, ptr->Cache.LineSize, cacheType);
}
+27 -25
View File
@@ -7,50 +7,53 @@
static FFlist cpuTimes1;
static uint64_t startTime;
void ffPrepareCPUUsage(void)
{
if (cpuTimes1.elementSize != 0) return; // Already prepared
void ffPrepareCPUUsage(void) {
if (cpuTimes1.elementSize != 0) {
return; // Already prepared
}
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
ffGetCpuUsageInfo(&cpuTimes1);
startTime = ffTimeGetNow();
}
const char* ffGetCpuUsageResult(FFCPUUsageOptions* options, FFlist* result)
{
const char* ffGetCpuUsageResult(FFCPUUsageOptions* options, FFlist* result) {
const char* error = NULL;
if(cpuTimes1.elementSize == 0)
{
if (cpuTimes1.elementSize == 0) {
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
error = ffGetCpuUsageInfo(&cpuTimes1);
if(error) return error;
if (error) {
return error;
}
ffTimeSleep(options->waitTime);
}
else
{
} else {
uint64_t elapsedTime = ffTimeGetNow() - startTime;
if (elapsedTime < options->waitTime)
ffTimeSleep(options->waitTime - (uint32_t)elapsedTime);
if (elapsedTime < options->waitTime) {
ffTimeSleep(options->waitTime - (uint32_t) elapsedTime);
}
}
if(cpuTimes1.length == 0) return "No CPU cores found";
if (cpuTimes1.length == 0) {
return "No CPU cores found";
}
FF_LIST_AUTO_DESTROY cpuTimes2 = ffListCreate(sizeof(FFCpuUsageInfo));
uint32_t retryCount = 0;
retry:
error = ffGetCpuUsageInfo(&cpuTimes2);
if(error) return error;
if(cpuTimes1.length != cpuTimes2.length) return "Unexpected CPU usage result";
if (error) {
return error;
}
if (cpuTimes1.length != cpuTimes2.length) {
return "Unexpected CPU usage result";
}
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
{
for (uint32_t i = 0; i < cpuTimes1.length; ++i) {
FFCpuUsageInfo* cpuTime1 = FF_LIST_GET(FFCpuUsageInfo, cpuTimes1, i);
FFCpuUsageInfo* cpuTime2 = FF_LIST_GET(FFCpuUsageInfo, cpuTimes2, i);
if (cpuTime2->totalAll <= cpuTime1->totalAll)
{
if (++retryCount <= 3)
{
if (cpuTime2->totalAll <= cpuTime1->totalAll) {
if (++retryCount <= 3) {
ffListClear(&cpuTimes2);
ffTimeSleep(options->waitTime);
goto retry;
@@ -59,11 +62,10 @@ retry:
}
}
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
{
for (uint32_t i = 0; i < cpuTimes1.length; ++i) {
FFCpuUsageInfo* cpuTime1 = FF_LIST_GET(FFCpuUsageInfo, cpuTimes1, i);
FFCpuUsageInfo* cpuTime2 = FF_LIST_GET(FFCpuUsageInfo, cpuTimes2, i);
*(double*) ffListAdd(result) = (double)(cpuTime2->inUseAll - cpuTime1->inUseAll) / (double)(cpuTime2->totalAll - cpuTime1->totalAll) * 100;
*(double*) ffListAdd(result) = (double) (cpuTime2->inUseAll - cpuTime1->inUseAll) / (double) (cpuTime2->totalAll - cpuTime1->totalAll) * 100;
cpuTime1->inUseAll = cpuTime2->inUseAll;
cpuTime1->totalAll = cpuTime2->totalAll;
}
+9 -11
View File
@@ -5,28 +5,26 @@
#include <mach/mach_host.h>
#include <mach/vm_map.h>
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
const char* ffGetCpuUsageInfo(FFlist* cpuTimes) {
natural_t numCPUs = 0U;
processor_info_array_t cpuInfo;
mach_msg_type_number_t numCpuInfo;
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS)
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS) {
return "host_processor_info() failed";
if (numCPUs * CPU_STATE_MAX != numCpuInfo)
}
if (numCPUs * CPU_STATE_MAX != numCpuInfo) {
return "Unexpected host_processor_info() result";
}
for (natural_t i = 0U; i < numCPUs; ++i)
{
integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
for (natural_t i = 0U; i < numCPUs; ++i) {
integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER] + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM] + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
.inUseAll = (uint64_t) inUse,
.totalAll = (uint64_t) total,
};
}
+17 -15
View File
@@ -7,23 +7,24 @@
#include <stdlib.h>
#if __OpenBSD__ || __NetBSD__
#include <sys/sched.h>
# include <sys/sched.h>
#endif
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
const char* ffGetCpuUsageInfo(FFlist* cpuTimes) {
size_t neededLength = 0;
#if __OpenBSD__|| __NetBSD__
#ifdef KERN_CPTIME
int ctls[] = {CTL_KERN, KERN_CPTIME};
#else
int ctls[] = {CTL_KERN, KERN_CP_TIME};
#endif
if (sysctl(ctls, 2, NULL, &neededLength, NULL, 0) != 0)
#if __OpenBSD__ || __NetBSD__
# ifdef KERN_CPTIME
int ctls[] = {CTL_KERN, KERN_CPTIME};
# else
int ctls[] = {CTL_KERN, KERN_CP_TIME};
# endif
if (sysctl(ctls, 2, NULL, &neededLength, NULL, 0) != 0) {
return "sysctl({CTL_KERN, KERN_CPTIME}, 2, NULL) failed";
}
#else
if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0)
if (sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0) {
return "sysctlbyname(kern.cp_times, NULL) failed";
}
#endif
uint32_t coreCount = (uint32_t) (neededLength / (CPUSTATES * sizeof(uint64_t)));
@@ -32,15 +33,16 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength);
#if __OpenBSD__ || __NetBSD__
if (sysctl(ctls, 2, cpTimes, &neededLength, NULL, 0) != 0)
if (sysctl(ctls, 2, cpTimes, &neededLength, NULL, 0) != 0) {
return "sysctl({CTL_KERN, KERN_CPTIME}, 2, NULL) failed";
}
#else
if(sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0)
if (sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0) {
return "sysctlbyname(kern.cp_times, cpTime) failed";
}
#endif
for (uint32_t i = 0; i < coreCount; ++i)
{
for (uint32_t i = 0; i < coreCount; ++i) {
uint64_t* cpTime = cpTimes[i];
uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS] + cpTime[CP_INTR];
uint64_t total = inUse + cpTime[CP_IDLE];
+6 -6
View File
@@ -4,20 +4,20 @@
#include <OS.h>
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
const char* ffGetCpuUsageInfo(FFlist* cpuTimes) {
system_info sysInfo;
if (get_system_info(&sysInfo) != B_OK)
if (get_system_info(&sysInfo) != B_OK) {
return "get_system_info() failed";
}
FF_AUTO_FREE cpu_info* cpuInfo = malloc(sizeof(*cpuInfo) * sysInfo.cpu_count);
if (get_cpu_info(0, sysInfo.cpu_count, cpuInfo) != B_OK)
if (get_cpu_info(0, sysInfo.cpu_count, cpuInfo) != B_OK) {
return "get_cpu_info() failed";
}
uint64_t uptime = (uint64_t) system_time();
for (uint32_t i = 0; i < sysInfo.cpu_count; ++i)
{
for (uint32_t i = 0; i < sysInfo.cpu_count; ++i) {
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
info->inUseAll = (uint64_t) cpuInfo[i].active_time;
info->totalAll = uptime;
+13 -16
View File
@@ -5,32 +5,29 @@
#include <stdio.h>
#include <inttypes.h>
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
const char* ffGetCpuUsageInfo(FFlist* cpuTimes) {
char buf[PROC_FILE_BUFFSIZ];
ssize_t nRead = ffReadFileData("/proc/stat", ARRAY_SIZE(buf) - 1, buf);
if(nRead < 0)
{
#ifdef __ANDROID__
if (nRead < 0) {
#ifdef __ANDROID__
return "Accessing \"/proc/stat\" is restricted on Android O+";
#else
#else
return "ffReadFileData(\"/proc/stat\", ARRAY_SIZE(buf) - 1, buf) failed";
#endif
#endif
}
buf[nRead] = '\0';
// Skip first line
char *start = NULL;
if((start = strchr(buf, '\n')) == NULL)
char* start = NULL;
if ((start = strchr(buf, '\n')) == NULL) {
return "skip first line failed";
}
++start;
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
char *token = NULL;
while ((token = strchr(start, '\n')))
{
if(sscanf(start, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7)
{
char* token = NULL;
while ((token = strchr(start, '\n'))) {
if (sscanf(start, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7) {
uint64_t inUse = user + nice + system + irq + softirq;
uint64_t total = inUse + idle + iowait;
@@ -39,9 +36,9 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
.inUseAll = inUse,
.totalAll = total,
};
}
else
} else {
break;
}
start = token + 1;
}
+1 -2
View File
@@ -1,7 +1,6 @@
#include "fastfetch.h"
#include "detection/cpuusage/cpuusage.h"
const char* ffGetCpuUsageInfo(FF_MAYBE_UNUSED FFlist* cpuTimes)
{
const char* ffGetCpuUsageInfo(FF_MAYBE_UNUSED FFlist* cpuTimes) {
return "Not support on this platform";
}
+9 -9
View File
@@ -4,26 +4,26 @@
#include <kstat.h>
#include <sys/sysinfo.h>
static inline void kstatFreeWrap(kstat_ctl_t** pkc)
{
static inline void kstatFreeWrap(kstat_ctl_t** pkc) {
assert(pkc);
if (*pkc)
if (*pkc) {
kstat_close(*pkc);
}
}
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
const char* ffGetCpuUsageInfo(FFlist* cpuTimes) {
__attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open();
if (!kc)
if (!kc) {
return "kstat_open() failed";
}
for (int i = 0;; ++i)
{
for (int i = 0;; ++i) {
kstat_t* ks = kstat_lookup(kc, "cpu_stat", i, NULL);
cpu_stat_t cs;
if (!ks || kstat_read(kc, ks, &cs) < 0)
if (!ks || kstat_read(kc, ks, &cs) < 0) {
break;
}
uint64_t inUse = cs.cpu_sysinfo.cpu[CPU_USER] + cs.cpu_sysinfo.cpu[CPU_KERNEL];
uint64_t total = inUse + cs.cpu_sysinfo.cpu[CPU_IDLE] + cs.cpu_sysinfo.cpu[CPU_WAIT];
+57 -58
View File
@@ -8,25 +8,25 @@
#include "common/windows/perflib_.h"
#include "common/windows/nt.h"
static const char* getInfoByNqsi(FFlist* cpuTimes)
{
static const char* getInfoByNqsi(FFlist* cpuTimes) {
ULONG size = 0;
if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
if (NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) {
return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL) failed";
}
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* FF_AUTO_FREE pinfo = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*)malloc(size);
if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, pinfo, size, &size)))
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* FF_AUTO_FREE pinfo = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*) malloc(size);
if (!NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, pinfo, size, &size))) {
return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, size) failed";
}
for (uint32_t i = 0; i < size / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); ++i)
{
for (uint32_t i = 0; i < size / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); ++i) {
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* coreInfo = pinfo + i;
// KernelTime includes IdleTime and DpcTime.
coreInfo->KernelTime.QuadPart -= coreInfo->IdleTime.QuadPart;
uint64_t inUse = (uint64_t) (coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart);
uint64_t total = inUse + (uint64_t)coreInfo->IdleTime.QuadPart;
uint64_t total = inUse + (uint64_t) coreInfo->IdleTime.QuadPart;
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
@@ -38,21 +38,18 @@ static const char* getInfoByNqsi(FFlist* cpuTimes)
return NULL;
}
static const char* getInfoByPerflib(FFlist* cpuTimes)
{
static const char* getInfoByPerflib(FFlist* cpuTimes) {
static HANDLE hQuery = NULL;
if (hQuery == NULL)
{
struct FFPerfQuerySpec
{
if (hQuery == NULL) {
struct FFPerfQuerySpec {
PERF_COUNTER_IDENTIFIER Identifier;
WCHAR Name[16];
} querySpec = {
.Identifier = {
// Processor Information GUID
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{b4fc721a-0378-476f-89ba-a5a79f810b36}
.CounterSetGuid = { 0xb4fc721a, 0x0378, 0x476f, {0x89, 0xba, 0xa5, 0xa7, 0x9f, 0x81, 0x0b, 0x36} },
.CounterSetGuid = {0xb4fc721a, 0x0378, 0x476f, {0x89, 0xba, 0xa5, 0xa7, 0x9f, 0x81, 0x0b, 0x36}},
.Size = sizeof(querySpec),
.CounterId = PERF_WILDCARD_COUNTER, // https://learn.microsoft.com/en-us/windows/win32/perfctrs/using-the-perflib-functions-to-consume-counter-data
.InstanceId = PERF_WILDCARD_COUNTER,
@@ -60,84 +57,86 @@ static const char* getInfoByPerflib(FFlist* cpuTimes)
.Name = PERF_WILDCARD_INSTANCE,
};
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
{
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS) {
PerfCloseQueryHandle(hQuery);
hQuery = INVALID_HANDLE_VALUE;
return "PerfOpenQueryHandle() failed";
}
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
{
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS) {
PerfCloseQueryHandle(hQuery);
hQuery = INVALID_HANDLE_VALUE;
return "PerfAddCounters() failed";
}
if (querySpec.Identifier.Status != ERROR_SUCCESS)
{
if (querySpec.Identifier.Status != ERROR_SUCCESS) {
PerfCloseQueryHandle(hQuery);
hQuery = INVALID_HANDLE_VALUE;
return "PerfAddCounters() reports invalid identifier";
}
}
if (hQuery == INVALID_HANDLE_VALUE)
if (hQuery == INVALID_HANDLE_VALUE) {
return "Init hQuery failed";
}
DWORD dataSize = 0;
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY) {
return "PerfQueryCounterData(NULL) failed";
}
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER))
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER)) {
return "instance doesn't exist";
}
FF_AUTO_FREE PERF_DATA_HEADER* const pDataHeader = (PERF_DATA_HEADER*)malloc(dataSize);
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS)
FF_AUTO_FREE PERF_DATA_HEADER* const pDataHeader = (PERF_DATA_HEADER*) malloc(dataSize);
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS) {
return "PerfQueryCounterData(pDataHeader) failed";
}
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*)(pDataHeader + 1);
if (pCounterHeader->dwType != PERF_COUNTERSET)
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*) (pDataHeader + 1);
if (pCounterHeader->dwType != PERF_COUNTERSET) {
return "Invalid counter type";
}
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*)(pCounterHeader + 1);
if (pMultiCounters->dwCounters == 0)
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*) (pCounterHeader + 1);
if (pMultiCounters->dwCounters == 0) {
return "No CPU counters found";
}
PERF_MULTI_INSTANCES* pMultiInstances = (PERF_MULTI_INSTANCES*)((BYTE*)pMultiCounters + pMultiCounters->dwSize);
if (pMultiInstances->dwInstances == 0)
PERF_MULTI_INSTANCES* pMultiInstances = (PERF_MULTI_INSTANCES*) ((BYTE*) pMultiCounters + pMultiCounters->dwSize);
if (pMultiInstances->dwInstances == 0) {
return "No CPU instances found";
}
PERF_INSTANCE_HEADER* pInstanceHeader = (PERF_INSTANCE_HEADER*)(pMultiInstances + 1);
for (DWORD iInstance = 0; iInstance < pMultiInstances->dwInstances; ++iInstance)
{
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pInstanceHeader + sizeof(*pInstanceHeader));
PERF_INSTANCE_HEADER* pInstanceHeader = (PERF_INSTANCE_HEADER*) (pMultiInstances + 1);
for (DWORD iInstance = 0; iInstance < pMultiInstances->dwInstances; ++iInstance) {
const wchar_t* instanceName = (const wchar_t*) ((BYTE*) pInstanceHeader + sizeof(*pInstanceHeader));
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pInstanceHeader + pInstanceHeader->Size);
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*) ((BYTE*) pInstanceHeader + pInstanceHeader->Size);
uint64_t processorUtility = UINT64_MAX, utilityBase = UINT64_MAX;
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++)
{
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++) {
DWORD* pCounterIds = (DWORD*) (pMultiCounters + 1);
// https://learn.microsoft.com/en-us/windows/win32/perfctrs/using-the-perflib-functions-to-consume-counter-data
switch (pCounterIds[iCounter]) {
case 26: // % Processor Utility (#26, Type=PERF_AVERAGE_BULK)
assert(pCounterData->dwDataSize == sizeof(uint64_t));
processorUtility = *(uint64_t*)(pCounterData + 1);
break;
case 27: // % Utility Base (#27, Type=PERF_AVERAGE_BASE)
assert(pCounterData->dwDataSize == sizeof(uint32_t));
utilityBase = *(uint32_t*)(pCounterData + 1) * 100LLU;
break;
case 26: // % Processor Utility (#26, Type=PERF_AVERAGE_BULK)
assert(pCounterData->dwDataSize == sizeof(uint64_t));
processorUtility = *(uint64_t*) (pCounterData + 1);
break;
case 27: // % Utility Base (#27, Type=PERF_AVERAGE_BASE)
assert(pCounterData->dwDataSize == sizeof(uint32_t));
utilityBase = *(uint32_t*) (pCounterData + 1) * 100LLU;
break;
}
pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pCounterData + pCounterData->dwSize);
pCounterData = (PERF_COUNTER_DATA*) ((BYTE*) pCounterData + pCounterData->dwSize);
}
if (wcschr(instanceName, L'_') == NULL /* ignore `_Total` */)
{
if (processorUtility == UINT64_MAX)
if (wcschr(instanceName, L'_') == NULL /* ignore `_Total` */) {
if (processorUtility == UINT64_MAX) {
return "Counter \"% Processor Utility\" are not supported";
}
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
@@ -146,21 +145,21 @@ static const char* getInfoByPerflib(FFlist* cpuTimes)
};
}
pInstanceHeader = (PERF_INSTANCE_HEADER*)pCounterData;
pInstanceHeader = (PERF_INSTANCE_HEADER*) pCounterData;
}
return NULL;
}
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
const char* ffGetCpuUsageInfo(FFlist* cpuTimes) {
const char* error = NULL;
if (ffIsWindows10OrGreater())
{
if (ffIsWindows10OrGreater()) {
error = getInfoByPerflib(cpuTimes);
FF_DEBUG("Get CPU usage info by Perflib: %s", error ?: "success");
if (!error) return NULL;
if (!error) {
return NULL;
}
ffListClear(cpuTimes);
}
+1 -2
View File
@@ -3,8 +3,7 @@
#include "fastfetch.h"
#include "modules/cursor/option.h"
typedef struct FFCursorResult
{
typedef struct FFCursorResult {
FFstrbuf theme;
FFstrbuf size;
FFstrbuf error;
+33 -37
View File
@@ -9,58 +9,54 @@
#include <stdlib.h>
static bool detectCursorGTK(FFCursorResult* result)
{
static bool detectCursorGTK(FFCursorResult* result) {
const FFGTKResult* gtk = ffDetectGTK4();
if(gtk->cursor.length == 0)
if (gtk->cursor.length == 0) {
gtk = ffDetectGTK3();
}
if(gtk->cursor.length == 0)
if (gtk->cursor.length == 0) {
gtk = ffDetectGTK2();
}
if(gtk->cursor.length == 0)
if (gtk->cursor.length == 0) {
return false;
}
ffStrbufAppend(&result->theme, &gtk->cursor);
ffStrbufAppend(&result->size, &gtk->cursorSize);
return true;
}
static void detectCursorFromConfigFile(const char* relativeFilePath, const char* themeStart, const char* themeDefault, const char* sizeStart, const char* sizeDefault, FFCursorResult* result)
{
if(ffParsePropFileConfigValues(relativeFilePath, 2, (FFpropquery[]) {
{themeStart, &result->theme},
{sizeStart, &result->size}
})) {
if(result->theme.length == 0)
static void detectCursorFromConfigFile(const char* relativeFilePath, const char* themeStart, const char* themeDefault, const char* sizeStart, const char* sizeDefault, FFCursorResult* result) {
if (ffParsePropFileConfigValues(relativeFilePath, 2, (FFpropquery[]) {{themeStart, &result->theme}, {sizeStart, &result->size}})) {
if (result->theme.length == 0) {
ffStrbufAppendS(&result->theme, themeDefault);
}
if(result->size.length == 0)
if (result->size.length == 0) {
ffStrbufAppendS(&result->size, sizeDefault);
}
}
if(result->theme.length == 0)
if (result->theme.length == 0) {
ffStrbufAppendF(&result->error, "Couldn't find cursor in %s", relativeFilePath);
}
}
static bool detectCursorFromXResources(FFCursorResult* result)
{
ffParsePropFileHomeValues(".Xresources", 2, (FFpropquery[]) {
{"Xcursor.theme :", &result->theme},
{"Xcursor.size :", &result->size}
});
static bool detectCursorFromXResources(FFCursorResult* result) {
ffParsePropFileHomeValues(".Xresources", 2, (FFpropquery[]) {{"Xcursor.theme :", &result->theme}, {"Xcursor.size :", &result->size}});
return result->theme.length > 0;
}
static bool detectCursorFromEnv(FFCursorResult* result)
{
static bool detectCursorFromEnv(FFCursorResult* result) {
const char* xcursor_theme = getenv("XCURSOR_THEME");
if(!ffStrSet(xcursor_theme))
if (!ffStrSet(xcursor_theme)) {
return false;
}
ffStrbufAppendS(&result->theme, xcursor_theme);
ffStrbufAppendS(&result->size, getenv("XCURSOR_SIZE"));
@@ -68,12 +64,12 @@ static bool detectCursorFromEnv(FFCursorResult* result)
return true;
}
static bool detectCursorHyprcursor(FFCursorResult* result)
{
static bool detectCursorHyprcursor(FFCursorResult* result) {
const char* hyprcursor_theme = getenv("HYPRCURSOR_THEME");
if(!ffStrSet(hyprcursor_theme))
if (!ffStrSet(hyprcursor_theme)) {
return false;
}
ffStrbufAppendS(&result->theme, hyprcursor_theme);
ffStrbufAppendS(&result->size, getenv("HYPRCURSOR_SIZE"));
@@ -81,25 +77,25 @@ static bool detectCursorHyprcursor(FFCursorResult* result)
return true;
}
void ffDetectCursor(FFCursorResult* result)
{
void ffDetectCursor(FFCursorResult* result) {
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
if(ffStrbufEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG))
if (ffStrbufEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG)) {
ffStrbufAppendS(&result->error, "WSLg uses native windows cursor");
else if(ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY))
} else if (ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY)) {
ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY");
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA))
} else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA)) {
detectCursorFromConfigFile("kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
} else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT)) {
detectCursorFromConfigFile("lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result);
else if(ffStrbufIgnCaseEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_HYPRLAND) && detectCursorHyprcursor(result))
} else if (ffStrbufIgnCaseEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_HYPRLAND) && detectCursorHyprcursor(result)) {
return;
else if(
} else if (
!detectCursorGTK(result) &&
!detectCursorFromEnv(result) &&
!ffParsePropFileHome(".icons/default/index.theme", "Inherits =", &result->theme) &&
!detectCursorFromXResources(result) &&
!ffParsePropFileData("icons/default/index.theme", "Inherits =", &result->theme)
) ffStrbufAppendS(&result->error, "Couldn't find cursor");
!ffParsePropFileData("icons/default/index.theme", "Inherits =", &result->theme)) {
ffStrbufAppendS(&result->error, "Couldn't find cursor");
}
}
+1 -2
View File
@@ -1,6 +1,5 @@
#include "cursor.h"
void ffDetectCursor(FF_MAYBE_UNUSED FFCursorResult* result)
{
void ffDetectCursor(FF_MAYBE_UNUSED FFCursorResult* result) {
ffStrbufInitS(&result->error, "Not supported on this platform");
}

Some files were not shown because too many files have changed in this diff Show More