Merge pull request #4775 from jmarshallnz/empty_episode_playcount
[vuplus_xbmc] / xbmc / osx / smc.c
1 /*
2  * Apple System Management Control (SMC) Tool
3  * Copyright (C) 2006 devnull
4  *
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.
9  
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.
14  
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.
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <IOKit/IOKitLib.h>
23
24 #include "smc.h"
25
26 static io_connect_t conn;
27
28 UInt32 _strtoul(const char *str, int size, int base)
29 {
30   UInt32 total = 0;
31   int i;
32   
33   for (i = 0; i < size; i++)
34   {
35     if (base == 16)
36       total += str[i] << (size - 1 - i) * 8;
37     else
38       total += (unsigned char) (str[i] << (size - 1 - i) * 8);
39   }
40   return total;
41 }
42
43 void _ultostr(char *str, UInt32 val)
44 {
45   str[0] = '\0';
46   sprintf(str, "%c%c%c%c",
47           (unsigned int) val >> 24,
48           (unsigned int) val >> 16,
49           (unsigned int) val >> 8,
50           (unsigned int) val);
51 }
52
53 kern_return_t SMCOpen(void)
54 {
55   kern_return_t result;
56   mach_port_t   masterPort;
57   io_iterator_t iterator;
58   io_object_t   device;
59   
60   result = IOMasterPort(MACH_PORT_NULL, &masterPort);
61   
62   CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
63   result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
64   if (result != kIOReturnSuccess)
65   {
66     printf("Error: IOServiceGetMatchingServices() = %08x\n", result);
67     return 1;
68   }
69   
70   device = IOIteratorNext(iterator);
71   IOObjectRelease(iterator);
72   if (device == 0)
73   {
74     printf("Error: no SMC found\n");
75     return 1;
76   }
77   
78   result = IOServiceOpen(device, mach_task_self(), 0, &conn);
79   IOObjectRelease(device);
80   if (result != kIOReturnSuccess)
81   {
82     printf("Error: IOServiceOpen() = %08x\n", result);
83     return 1;
84   }
85   
86   return kIOReturnSuccess;
87 }
88
89 kern_return_t SMCClose()
90 {
91   return IOServiceClose(conn);
92 }
93
94
95 kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure)
96 {
97   size_t   structureInputSize;
98   size_t   structureOutputSize;
99   
100   structureInputSize = sizeof(SMCKeyData_t);
101   structureOutputSize = sizeof(SMCKeyData_t);
102   
103 #if MAC_OS_X_VERSION_10_5
104   return IOConnectCallStructMethod( conn, index,
105                                    // inputStructure
106                                    inputStructure, structureInputSize,
107                                    // ouputStructure
108                                    outputStructure, &structureOutputSize );
109 #else
110   return IOConnectMethodStructureIStructureO( conn, index,
111                                              structureInputSize, /* structureInputSize */
112                                              &structureOutputSize,   /* structureOutputSize */
113                                              inputStructure,        /* inputStructure */
114                                              outputStructure);       /* ouputStructure */
115 #endif
116   
117 }
118
119 kern_return_t SMCReadKey(UInt32ConstChar_t key, SMCVal_t *val)
120 {
121   kern_return_t result;
122   SMCKeyData_t  inputStructure;
123   SMCKeyData_t  outputStructure;
124   
125   memset(&inputStructure, 0, sizeof(SMCKeyData_t));
126   memset(&outputStructure, 0, sizeof(SMCKeyData_t));
127   memset(val, 0, sizeof(SMCVal_t));
128   
129   inputStructure.key = _strtoul(key, 4, 16);
130   inputStructure.data8 = SMC_CMD_READ_KEYINFO;
131   
132   result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
133   if (result != kIOReturnSuccess)
134     return result;
135   
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;
140   
141   result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
142   if (result != kIOReturnSuccess)
143     return result;
144   
145   memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
146   
147   return kIOReturnSuccess;
148 }
149
150 double SMCGetTemperature(const char *key)
151 {
152   SMCVal_t val;
153   kern_return_t result;
154   SMCOpen();
155   result = SMCReadKey(key, &val);
156   SMCClose();
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;
164       }
165     }
166   }
167   // read failed
168   return 0.0;
169 }
170