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.

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"

smc keys for M3 pro chip, returning temperature values
 
 
Q