2 * Apple System Management Control (SMC) Tool
3 * Copyright (C) 2006 devnull
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <IOKit/IOKitLib.h>
26 static io_connect_t conn;
28 UInt32 _strtoul(const char *str, int size, int base)
33 for (i = 0; i < size; i++)
36 total += str[i] << (size - 1 - i) * 8;
38 total += (unsigned char) (str[i] << (size - 1 - i) * 8);
43 void _ultostr(char *str, UInt32 val)
46 sprintf(str, "%c%c%c%c",
47 (unsigned int) val >> 24,
48 (unsigned int) val >> 16,
49 (unsigned int) val >> 8,
53 kern_return_t SMCOpen(void)
56 mach_port_t masterPort;
57 io_iterator_t iterator;
60 result = IOMasterPort(MACH_PORT_NULL, &masterPort);
62 CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
63 result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
64 if (result != kIOReturnSuccess)
66 printf("Error: IOServiceGetMatchingServices() = %08x\n", result);
70 device = IOIteratorNext(iterator);
71 IOObjectRelease(iterator);
74 printf("Error: no SMC found\n");
78 result = IOServiceOpen(device, mach_task_self(), 0, &conn);
79 IOObjectRelease(device);
80 if (result != kIOReturnSuccess)
82 printf("Error: IOServiceOpen() = %08x\n", result);
86 return kIOReturnSuccess;
89 kern_return_t SMCClose()
91 return IOServiceClose(conn);
95 kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure)
97 size_t structureInputSize;
98 size_t structureOutputSize;
100 structureInputSize = sizeof(SMCKeyData_t);
101 structureOutputSize = sizeof(SMCKeyData_t);
103 #if MAC_OS_X_VERSION_10_5
104 return IOConnectCallStructMethod( conn, index,
106 inputStructure, structureInputSize,
108 outputStructure, &structureOutputSize );
110 return IOConnectMethodStructureIStructureO( conn, index,
111 structureInputSize, /* structureInputSize */
112 &structureOutputSize, /* structureOutputSize */
113 inputStructure, /* inputStructure */
114 outputStructure); /* ouputStructure */
119 kern_return_t SMCReadKey(UInt32ConstChar_t key, SMCVal_t *val)
121 kern_return_t result;
122 SMCKeyData_t inputStructure;
123 SMCKeyData_t outputStructure;
125 memset(&inputStructure, 0, sizeof(SMCKeyData_t));
126 memset(&outputStructure, 0, sizeof(SMCKeyData_t));
127 memset(val, 0, sizeof(SMCVal_t));
129 inputStructure.key = _strtoul(key, 4, 16);
130 inputStructure.data8 = SMC_CMD_READ_KEYINFO;
132 result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
133 if (result != kIOReturnSuccess)
136 val->dataSize = outputStructure.keyInfo.dataSize;
137 _ultostr(val->dataType, outputStructure.keyInfo.dataType);
138 inputStructure.keyInfo.dataSize = val->dataSize;
139 inputStructure.data8 = SMC_CMD_READ_BYTES;
141 result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
142 if (result != kIOReturnSuccess)
145 memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
147 return kIOReturnSuccess;
150 double SMCGetTemperature(const char *key)
153 kern_return_t result;
155 result = SMCReadKey(key, &val);
157 if (result == kIOReturnSuccess) {
158 // read succeeded - check returned value
159 if (val.dataSize > 0) {
160 if (strcmp(val.dataType, DATATYPE_SP78) == 0) {
161 // convert fp78 value to temperature
162 int intValue = (val.bytes[0] * 256 + val.bytes[1]) >> 2;
163 return intValue / 64.0;