From e3c44d46fa4e83a328ed40d97e77510277cfb8ef Mon Sep 17 00:00:00 2001 From: Sebastien Lavoie Date: Tue, 11 Sep 2018 11:43:11 -0400 Subject: [PATCH] Refactor and add gpu/fan --- smc.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++----------- smc.h | 1 + 2 files changed, 160 insertions(+), 37 deletions(-) diff --git a/smc.c b/smc.c index e32f3ea..5822451 100644 --- a/smc.c +++ b/smc.c @@ -173,11 +173,11 @@ double SMCGetFanSpeed(char *key) if (result == kIOReturnSuccess) { // read succeeded - check returned value if (val.dataSize > 0) { - if (strcmp(val.dataType, DATATYPE_FPE2) == 0) { - // convert fpe2 value to rpm - int intValue = (unsigned char)val.bytes[0] * 256 + (unsigned char)val.bytes[1]; - return intValue / 4.0; - } + if (strcmp(val.dataType, DATATYPE_FPE2) == 0) { + // convert fpe2 value to rpm + int intValue = (unsigned char)val.bytes[0] * 256 + (unsigned char)val.bytes[1]; + return intValue / 4.0; + } } } // read failed @@ -189,52 +189,174 @@ double convertToFahrenheit(double celsius) { return (celsius * (9.0 / 5.0)) + 32.0; } +// Requires SMCOpen() +void readAndPrintCpuTemp(int show_title, char scale) { + double temperature = SMCGetTemperature(SMC_KEY_CPU_TEMP); + if (scale == 'F') { + temperature = convertToFahrenheit(temperature); + } + + char *title = ""; + if (show_title) { + title = "CPU: "; + } + printf("%s%0.1f°%c\n", title, temperature, scale); +} + +// Requires SMCOpen() +void readAndPrintGpuTemp(int show_title, char scale) { + double temperature = SMCGetTemperature(SMC_KEY_GPU_TEMP); + if (scale == 'F') { + temperature = convertToFahrenheit(temperature); + } + + char *title = ""; + if (show_title) { + title = "GPU: "; + } + printf("%s%0.1f°%c\n", title, temperature, scale); +} + +float SMCGetFanRPM(char *key) +{ + SMCVal_t val; + kern_return_t result; + + result = SMCReadKey(key, &val); + if (result == kIOReturnSuccess) { + // read succeeded - check returned value + if (val.dataSize > 0) { + if (strcmp(val.dataType, DATATYPE_FPE2) == 0) { + // convert fpe2 value to RPM + return ntohs(*(UInt16*)val.bytes) / 4.0; + } + } + } + // read failed + return -1.f; +} + +// Requires SMCOpen() +void readAndPrintFanRPMs(void) +{ + kern_return_t result; + SMCVal_t val; + UInt32Char_t key; + int totalFans, i; + + result = SMCReadKey("FNum", &val); + + if(result == kIOReturnSuccess) + { + totalFans = _strtoul((char *)val.bytes, val.dataSize, 10); + + printf("Num fans: %d\n", totalFans); + for(i = 0; i < totalFans; i++) { + sprintf(key, "F%dID", i); + result = SMCReadKey(key, &val); + if (result != kIOReturnSuccess) { + continue; + } + char* name = val.bytes + 4; + + sprintf(key, "F%dAc", i); + float actual_speed = SMCGetFanRPM(key); + if (actual_speed < 0.f) { + continue; + } + + sprintf(key, "F%dMn", i); + float minimum_speed = SMCGetFanRPM(key); + if (minimum_speed < 0.f) { + continue; + } + + sprintf(key, "F%dMx", i); + float maximum_speed = SMCGetFanRPM(key); + if (maximum_speed < 0.f) { + continue; + } + + float rpm = actual_speed - minimum_speed; + if (rpm < 0.f) { + rpm = 0.f; + } + float pct = rpm / (maximum_speed - minimum_speed); + + pct *= 100.f; + printf("Fan %d - %s at %.0f RPM (%.0f%%)\n", i, name, rpm, pct); + + //sprintf(key, "F%dSf", i); + //SMCReadKey(key, &val); + //printf(" Safe speed : %.0f\n", strtof(val.bytes, val.dataSize, 2)); + //sprintf(key, "F%dTg", i); + //SMCReadKey(key, &val); + //printf(" Target speed : %.0f\n", strtof(val.bytes, val.dataSize, 2)); + //SMCReadKey("FS! ", &val); + //if ((_strtoul((char *)val.bytes, 2, 16) & (1 << i)) == 0) + // printf(" Mode : auto\n"); + //else + // printf(" Mode : forced\n"); + } + } +} + int main(int argc, char *argv[]) { char scale = 'C'; + int cpu = 0; int fan = 0; + int gpu = 0; int c; - while ((c = getopt(argc, argv, "CFf")) != -1) { - switch (c) { - case 'F': - case 'C': - scale = c; - break; - case 'f': - fan = 1; - break; - } + while ((c = getopt(argc, argv, "CFcfgh?")) != -1) { + switch (c) { + case 'F': + case 'C': + scale = c; + break; + case 'c': + cpu = 1; + break; + case 'f': + fan = 1; + break; + case 'g': + gpu = 1; + break; + case 'h': + case '?': + printf("usage: osx-cpu-temp \n"); + printf("Options:\n"); + printf(" -F Display temperatures in degrees Fahrenheit.\n"); + printf(" -C Display temperatures in degrees Celsius (Default).\n"); + printf(" -c Display CPU temperature (Default).\n"); + printf(" -g Display GPU temperature.\n"); + printf(" -f Display fan speeds.\n"); + printf(" -h Display this help.\n"); + printf("\nIf more than one of -c, -f, or -g are specified, titles will be added\n"); + return -1; + } + } + + if (!fan && !gpu) { + cpu = 1; } - int nfans = 0; - double fans[10]; + int show_title = fan + gpu + cpu > 1; SMCOpen(); - double temperature = SMCGetTemperature(SMC_KEY_CPU_TEMP); - int i; - for (i = 0; i < 10; i++) { - char key[5] = SMC_KEY_FAN0_RPM_CUR; - key[1] += i; - double speed = SMCGetFanSpeed(key); - if (speed != 0) { - fans[nfans++] = speed; - } - } - SMCClose(); - if (scale == 'F') { - temperature = convertToFahrenheit(temperature); + if (cpu) { + readAndPrintCpuTemp(show_title, scale); + } + if (gpu) { + readAndPrintGpuTemp(show_title, scale); } - - printf("%0.1f°%c", temperature, scale); if (fan) { - int i; - for (i = 0; i < nfans; i++) { - printf(" %0.1frpm", fans[i]); - } + readAndPrintFanRPMs(); } - printf("\n"); + SMCClose(); return 0; } diff --git a/smc.h b/smc.h index f8d6430..a936209 100644 --- a/smc.h +++ b/smc.h @@ -40,6 +40,7 @@ // key values #define SMC_KEY_CPU_TEMP "TC0P" +#define SMC_KEY_GPU_TEMP "TG0P" #define SMC_KEY_FAN0_RPM_CUR "F0Ac" typedef struct {