1 /*
2  * Apple System Management Controller (SMC) API from user space for Intel based
3  * Macs. Works by talking to the AppleSMC.kext (kernel extension), the driver
4  * for the SMC.
5  *
6  * smc.h
7  * libsmc
8  *
9  * Copyright (C) 2014  beltex <https://github.com/beltex>
10  *
11  * Based off of fork from:
12  * osx-cpu-temp <https://github.com/lavoiesl/osx-cpu-temp>
13  *
14  * With credits to:
15  *
16  * Copyright (C) 2006 devnull
17  * Apple System Management Control (SMC) Tool
18  *
19  * Copyright (C) 2006 Hendrik Holtmann
20  * smcFanControl <https://github.com/hholtmann/smcFanControl>
21  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 2 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License along
33  * with this program; if not, write to the Free Software Foundation, Inc.,
34  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35  */
36 
37 #include <IOKit/IOKitLib.h>
38 
39 
40 //------------------------------------------------------------------------------
41 // MARK: MACROS
42 //------------------------------------------------------------------------------
43 
44 
45 /**
46 SMC keys for temperature sensors - 4 byte multi-character constants
47 
48 Not applicable to all Mac's of course. In adition, the definition of the codes
49 may not be 100% accurate necessarily. Finally, list is incomplete.
50 
51 Presumed letter translations:
52 
53 - T = Temperature (if first char)
54 - C = CPU
55 - G = GPU
56 - P = Proximity
57 - D = Diode
58 - H = Heatsink
59 
60 Sources:
61 
62 - https://www.apple.com/downloads/dashboard/status/istatpro.html
63 - https://github.com/hholtmann/smcFanControl
64 - https://github.com/jedda/OSX-Monitoring-Tools
65 - http://www.parhelia.ch/blog/statics/k3_keys.html
66 */
67 #define AMBIENT_AIR_0          "TA0P"
68 #define AMBIENT_AIR_1          "TA1P"
69 #define CPU_0_DIODE            "TC0D"
70 #define CPU_0_HEATSINK         "TC0H"
71 #define CPU_0_PROXIMITY        "TC0P"
72 #define ENCLOSURE_BASE_0       "TB0T"
73 #define ENCLOSURE_BASE_1       "TB1T"
74 #define ENCLOSURE_BASE_2       "TB2T"
75 #define ENCLOSURE_BASE_3       "TB3T"
76 #define GPU_0_DIODE            "TG0D"
77 #define GPU_0_HEATSINK         "TG0H"
78 #define GPU_0_PROXIMITY        "TG0P"
79 #define HARD_DRIVE_BAY         "TH0P"
80 #define MEMORY_SLOT_0          "TM0S"
81 #define MEMORY_SLOTS_PROXIMITY "TM0P"
82 #define NORTHBRIDGE            "TN0H"
83 #define NORTHBRIDGE_DIODE      "TN0D"
84 #define NORTHBRIDGE_PROXIMITY  "TN0P"
85 #define THUNDERBOLT_0          "TI0P"
86 #define THUNDERBOLT_1          "TI1P"
87 #define WIRELESS_MODULE        "TW0P"
88 
89 
90 /**
91 SMC keys for fans - 4 byte multi-character constants
92 
93 Number of fans on Macs vary of course, thus not all keys will be applicable.
94 
95 Presumed letter translations:
96 
97 - F  = Fan
98 - Ac = Acutal
99 - Mn = Min
100 - Mx = Max
101 - Sf = Safe
102 - Tg = Target
103 
104 Sources: See TMP SMC keys
105 */
106 #define FAN_0            "F0Ac"
107 #define FAN_0_MIN_RPM    "F0Mn"
108 #define FAN_0_MAX_RPM    "F0Mx"
109 #define FAN_0_SAFE_RPM   "F0Sf"
110 #define FAN_0_TARGET_RPM "F0Tg"
111 #define FAN_1            "F1Ac"
112 #define FAN_1_MIN_RPM    "F1Mn"
113 #define FAN_1_MAX_RPM    "F1Mx"
114 #define FAN_1_SAFE_RPM   "F1Sf"
115 #define FAN_1_TARGET_RPM "F1Tg"
116 #define FAN_2            "F2Ac"
117 #define FAN_2_MIN_RPM    "F2Mn"
118 #define FAN_2_MAX_RPM    "F2Mx"
119 #define FAN_2_SAFE_RPM   "F2Sf"
120 #define FAN_2_TARGET_RPM "F2Tg"
121 #define NUM_FANS         "FNum"
122 #define FORCE_BITS       "FS! "
123 
124 
125 /**
126 Misc SMC keys - 4 byte multi-character constants
127 
128 Sources: See TMP SMC keys
129 */
130 #define BATT_PWR "BATP"
131 #define NUM_KEYS "#KEY"
132 #define ODD_FULL "MSDI"
133 
134 
135 //------------------------------------------------------------------------------
136 // MARK: TYPES
137 //------------------------------------------------------------------------------
138 
139 
140 typedef char fan_name_t[13];
141 
142 
143 //------------------------------------------------------------------------------
144 // MARK: ENUMS
145 //------------------------------------------------------------------------------
146 
147 
148 typedef enum {
149     CELSIUS,
150     FAHRENHEIT,
151     KELVIN
152 } tmp_unit_t;
153 
154 
155 //------------------------------------------------------------------------------
156 // MARK: PROTOTYPES
157 //------------------------------------------------------------------------------
158 
159 
160 /**
161 Open a connection to the SMC
162 
163 :returns: kIOReturnSuccess on successful connection to the SMC.
164 */
165 kern_return_t open_smc(void);
166 kern_return_t open_smc_conn(io_connect_t *con);
167 
168 
169 /**
170 Close connection to the SMC
171 
172 :returns: kIOReturnSuccess on successful close of connection to the SMC.
173 */
174 kern_return_t close_smc(void);
175 kern_return_t close_smc_conn(io_connect_t con);
176 
177 /**
178 Check if an SMC key is valid. Useful for determining if a certain machine has
179 particular sensor or fan for example.
180 
181 :param: key The SMC key to check. 4 byte multi-character constant. Must be 4
182             characters in length.
183 :returns: True if the key is found, false otherwise
184 */
185 bool is_key_valid(char *key);
186 bool is_key_valid_conn(io_connect_t con, char *key);
187 
188 /**
189 Get the current temperature from a sensor
190 
191 :param: key The temperature sensor to read from
192 :param: unit The unit for the temperature value.
193 :returns: Temperature of sensor. If the sensor is not found, or an error
194           occurs, return will be zero
195 */
196 double get_tmp(char *key, tmp_unit_t unit);
197 double get_tmp_conn(io_connect_t con, char *key, tmp_unit_t unit);
198 
199 
200 /**
201 Is the machine being powered by the battery?
202 
203 :returns: True if it is, false otherwise
204 */
205 bool is_battery_powered(void);
206 
207 
208 /**
209 Is there a CD in the optical disk drive (ODD)?
210 
211 :returns: True if there is, false otherwise
212 */
213 bool is_optical_disk_drive_full(void);
214 
215 
216 /**
217 Get the name of a fan.
218 
219 :param: fanNum The number of the fan to check
220 :param: name The name of the fan. Return will be empty on error.
221 :returns: True if successful, false otherwise.
222 */
223 bool get_fan_name(unsigned int fan_num, fan_name_t name);
224 
225 
226 /**
227 Get the number of fans on this machine.
228 
229 :returns: The number of fans. If an error occurs, return will be -1.
230 */
231 int get_num_fans(void);
232 
233 
234 /**
235 Get the current speed (RPM - revolutions per minute) of a fan.
236 
237 :param: fan_num The number of the fan to check
238 :returns: The fan RPM. If the fan is not found, or an error occurs, return
239           will be zero
240 */
241 UInt get_fan_rpm(UInt fan_num);
242 
243 
244 /**
245 Set the minimum speed (RPM - revolutions per minute) of a fan. This method
246 requires root privileges. By minimum we mean that OS X can interject and
247 raise the fan speed if needed, however it will not go below this.
248 
249 WARNING: You are playing with hardware here, BE CAREFUL.
250 
251 :param: fan_num The number of the fan to set
252 :param: rpm The speed you would like to set the fan to.
253 :param: auth Should the function do authentication?
254 :return: True if successful, false otherwise
255 */
256 bool set_fan_min_rpm(unsigned int fan_num, unsigned int rpm, bool auth);
257