smc keys for M3 pro chip, returning temperature values

Im honestly a bit lost and looking for general pointers. Here is the general flow of my project. I have an Xcode project where I want to return and convert the temperature values accessed from the apple smc and I found a GitHub repo with all the smc key sensors for the M3Pros/Max chips: https://github.com/exelban/stats/issues/1703 basically, I have all these keys stored in an array in obj-c like so:

NSArray *smcKeys = @[ @"Tp01", @"Tp05", @"Tp09", @"Tp0D", @"Tp0b", @"Tp0f", @"Tp0j", @"Tp0n",@"Tp0h", @"Tp0L", @"Tp0S", @"Tp0V", @"Tp0z", @"Tp0v", @"Tp17", @"Tp1F", @"Tp1J", @"Tp1p", @"Tp1h", @"Tp1R", ];

I am passing all these keys by passing 'smcKeys' in a regular C code file I have here that is meant to open, close and read the data shown here:

#include "smc.h"
#include <mach/mach.h>
#include <IOKit/IOKitLib.h>
#include "smckeys.h"



io_connect_t conn;

kern_return_t openSMC(void) {
    
    kern_return_t result;
    kern_return_t service;
    io_iterator_t iterator;

    service = IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching("AppleSMC"), &iterator);
    if(service == 0) {
        printf("error: could not match dictionary");
        return 0;
    }
    result = IOServiceOpen(service, mach_task_self(), 0, &conn);
    IOObjectRelease(service);
    return 0;
}

kern_return_t closeSMC(void) {
    return IOServiceClose(conn);
    
}


kern_return_t readSMC(char *smcKeys, SMCVal_t *val) {
kern_return_t result;
uint32_t keyCode = *(uint32_t *)smcKeys;

SMCVal_t inputStruct;
SMCVal_t outputStruct;

inputStruct.datasize = sizeof(SMCVal_t);
inputStruct.datatype = 'I' << 24;         //a left shift operation. turning the I into an int by shifting the ASCII value 24 bits to the left

inputStruct.data[0] = keyCode;
result = IOConnectCallStructMethod(conn, 5, &inputStruct, sizeof(SMCVal_t), &outputStruct, (size_t*)&inputStruct.datasize);

if (result == kIOReturnSuccess) {
    if (val -> datasize > 0) {
        if (val -> datatype == ('f' << 24 | 'l' << 16 | 't' << 8 )) {    //bit shifting to from 32bit operation associated with the ASCII charecters'f', 'l', and 't', sets datatype field.
            double temp = *(double *)val -> data;
            return temp;
        }
    }
}
return 0.0;

}

Which I am then then calling the functions from this file in a swift file and converting the values to Fahrenheit but no data is being printed in my console:

import IOKit



public class getTemperature {
    
    public struct SMCVal_t {
        var datasize: UInt32
        var datatype: UInt32
        var data: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)
    }
    
    @_silgen_name("openSMC")
    func openSMC() -> kern_return_t
    
    @_silgen_name("closeSMC")
    func closeSMC() -> kern_return_t
    
    @_silgen_name("readSMC")
    func readSMC(key: UnsafePointer<CChar>?,val: UnsafeMutablePointer<SMCVal_t>) -> kern_return_t
    
    
    func convertAndPrintTempValue(key:UnsafePointer<CChar>?,scale: Character, showTemp: Bool ) -> kern_return_t {
        
        let openSM = openSMC()
        guard openSM == 0 else {
            print("Failed to open SMC: \(openSM)")
            return kern_return_t()
        }
        
        let closeSM = closeSMC()
        guard closeSM == 0 else {
            print("could not close SMC: \(closeSM)")
            return IOServiceClose(conn)
        }
        
        
        func convertAndPrint(val: SMCVal_t) -> Double {
            if val.datatype == (UInt32("f".utf8.first!) << 24 | UInt32("l".utf8.first!) << 16 | UInt32("t".utf8.first!) << 8)  {
                let extractedTemp = Double(val.data.0)
                return( extractedTemp * 9.0 / 5.0 + 32.0 )
            }
            return 0.0
        }
        
        let smcValue = SMCVal_t(datasize: 0, datatype: 0, data: (0,0,0,0,0,0,0,0))
        let convertedVal = convertAndPrint(val: smcValue)
        
        print("Temperarure:\(convertedVal)F°")
   
  
        return kern_return_t()
    }
       
}

I know this is a lot but I am honestly looking for any tips to fill in any gaps in my knowledge for anyone who's built a similar application meant to extract any sort of data from Mac hardware.

Replies

I’d love to help you with this — weird low-level programming is my favourite topic — but, as I’ve mentioned in your numerous other threads, your end goal is not something we support. Sorry.

I have two suggestions for you:

  • Pick some other low-level task, one that’s actually supportable, and use that as a learning exercise. You could then apply those lessons to this task.

  • Stick with this task but ask questions that are independent of this task. For example, if you asked how to parse a buffer of binary data in Swift, that’s something I can help you with.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • thank you ill try to single out more individual issues to hone in on. Im just a little confused why this is not a task that is very well documented or supported as theres many applications that are able to return the temperature values. My examples are apps like Macmade Hot, or the CPU temp feature thats built into Clean My Mac X.

Add a Comment