Changeset View
Changeset View
Standalone View
Standalone View
ksysguardd/Linux/acpi.c
1 | /* | 1 | /* | ||
---|---|---|---|---|---|
2 | KSysGuard, the KDE System Guard | 2 | KSysGuard, the KDE System Guard | ||
3 | 3 | | |||
4 | Copyright (c) 2003 Stephan Uhlmann <su@su2.info> | 4 | Copyright (c) 2003 Stephan Uhlmann <su@su2.info> | ||
5 | Copyright (c) 2005 Sirtaj Singh Kang <taj@kde.org> -- Battery fixes and Thermal | 5 | Copyright (c) 2005 Sirtaj Singh Kang <taj@kde.org> -- Battery fixes and Thermal | ||
6 | Copyright (c) 2020 Jose Jorge <lists.jjorge@free.fr> -- Add energy sensor | ||||
6 | 7 | | |||
7 | This program is free software; you can redistribute it and/or | 8 | This program is free software; you can redistribute it and/or | ||
8 | modify it under the terms of version 2 of the GNU General Public | 9 | modify it under the terms of version 2 of the GNU General Public | ||
9 | License as published by the Free Software Foundation. | 10 | License as published by the Free Software Foundation. | ||
10 | 11 | | |||
11 | This program is distributed in the hope that it will be useful, | 12 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
Show All 32 Lines | |||||
46 | } | 47 | } | ||
47 | 48 | | |||
48 | void exitAcpi( void ) | 49 | void exitAcpi( void ) | ||
49 | { | 50 | { | ||
50 | } | 51 | } | ||
51 | 52 | | |||
52 | 53 | | |||
53 | /************ ACPI Battery **********/ | 54 | /************ ACPI Battery **********/ | ||
54 | void registerBatteryCharge(int number, struct SensorModul *sm) | 55 | void registerBatteryCharge(char name, int number, struct SensorModul *sm) | ||
55 | { | 56 | { | ||
56 | char name[ ACPIFILENAMELENGTHMAX ]; | | |||
57 | readTypeFile("/sys/class/power_supply/BAT%d/type", number, name, sizeof(name)); | | |||
58 | | ||||
59 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | 57 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | ||
60 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/Charge", number, name); | 58 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/Charge", number, name); | ||
61 | 59 | | |||
62 | registerMonitor(sensorName, "integer", printSysBatteryCharge, | 60 | registerMonitor(sensorName, "float", printSysBatteryCharge, | ||
63 | printSysBatteryChargeInfo, sm); | 61 | printSysBatteryChargeInfo, sm); | ||
64 | } | 62 | } | ||
65 | 63 | | |||
66 | void registerBatteryChargeDesign(int number, struct SensorModul *sm) | 64 | void registerBatteryChargeDesign(char name, int number, struct SensorModul *sm) | ||
67 | { | 65 | { | ||
68 | char name[ ACPIFILENAMELENGTHMAX ]; | | |||
69 | readTypeFile("/sys/class/power_supply/BAT%d/type", number, name, sizeof(name)); | | |||
70 | | ||||
71 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | 66 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | ||
72 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/ChargeDesign", number, name); | 67 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/ChargeDesign", number, name); | ||
73 | 68 | | |||
74 | registerMonitor(sensorName, "integer", printSysBatteryChargeDesign, | 69 | registerMonitor(sensorName, "float", printSysBatteryChargeDesign, | ||
75 | printSysBatteryChargeDesignInfo, sm); | 70 | printSysBatteryChargeDesignInfo, sm); | ||
76 | } | 71 | } | ||
77 | 72 | | |||
78 | void registerBatteryRate(int number, struct SensorModul *sm) | 73 | void registerBatteryEnergy(char name, int number, struct SensorModul *sm) | ||
ahiemstra: Uhm, this should be `const char *name` right? I don't really see how this can work otherwise. | |||||
79 | { | 74 | { | ||
80 | char name[ ACPIFILENAMELENGTHMAX ]; | 75 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | ||
81 | readTypeFile("/sys/class/power_supply/BAT%d/type", number, name, sizeof(name)); | 76 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/Energy", number, name); | ||
These two lines are now repeated in all "registerX" functions. Maybe move this to initAcpiBattery and pass it to each function as a parameter? ahiemstra: These two lines are now repeated in all "registerX" functions. Maybe move this to… | |||||
77 | | ||||
78 | registerMonitor(sensorName, "float", printSysBatteryEnergy, | ||||
79 | printSysBatteryEnergyInfo, sm); | ||||
80 | } | ||||
82 | 81 | | |||
82 | void registerBatteryEnergyDesign(char name, int number, struct SensorModul *sm) | ||||
83 | { | ||||
84 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | ||||
85 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/EnergyDesign", number, name); | ||||
86 | | ||||
87 | registerMonitor(sensorName, "float", printSysBatteryEnergyDesign, | ||||
88 | printSysBatteryEnergyDesignInfo, sm); | ||||
89 | } | ||||
90 | | ||||
91 | void registerBatteryRate(char name, int number, struct SensorModul *sm) | ||||
92 | { | ||||
83 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | 93 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | ||
84 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/Rate", number, name); | 94 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/Rate", number, name); | ||
85 | 95 | | |||
86 | registerMonitor(sensorName, "integer", printSysBatteryRate, | 96 | registerMonitor(sensorName, "integer", printSysBatteryRate, | ||
87 | printSysBatteryRateInfo, sm); | 97 | printSysBatteryRateInfo, sm); | ||
88 | } | 98 | } | ||
89 | 99 | | |||
100 | void registerBatteryRatePower(char name, int number, struct SensorModul *sm) | ||||
101 | { | ||||
102 | char sensorName [ ACPIFILENAMELENGTHMAX ]; | ||||
103 | snprintf(sensorName, sizeof(sensorName), "acpi/Battery/%d-%s/RatePower", number, name); | ||||
104 | | ||||
105 | registerMonitor(sensorName, "integer", printSysBatteryRate, | ||||
106 | printSysBatteryRateInfo, sm); | ||||
107 | } | ||||
108 | | ||||
90 | void initAcpiBattery( struct SensorModul* sm ) | 109 | void initAcpiBattery( struct SensorModul* sm ) | ||
91 | { | 110 | { | ||
92 | DIR *d; | 111 | DIR *d; | ||
93 | struct dirent *de; | 112 | struct dirent *de; | ||
94 | char s[ ACPIFILENAMELENGTHMAX ]; | 113 | char name[ ACPIFILENAMELENGTHMAX ]; | ||
95 | 114 | | |||
96 | d = opendir("/sys/class/power_supply/"); | 115 | d = opendir("/sys/class/power_supply/"); | ||
97 | if (d != NULL) { | 116 | if (d != NULL) { | ||
98 | while ( (de = readdir(d)) != NULL ) { | 117 | while ( (de = readdir(d)) != NULL ) { | ||
99 | if (!de->d_name || de->d_name[0] == '.') | 118 | if (!de->d_name || de->d_name[0] == '.') | ||
100 | continue; | 119 | continue; | ||
101 | if (strncmp( de->d_name, "BAT", sizeof("BAT")-1) == 0) { | 120 | if (strncmp( de->d_name, "BAT", sizeof("BAT")-1) == 0) { | ||
102 | int number = atoi(de->d_name + (sizeof("BAT")-1)); | 121 | int number = atoi(de->d_name + (sizeof("BAT")-1)); | ||
103 | registerBatteryCharge(number, sm); | 122 | readTypeFile("/sys/class/power_supply/BAT%d/type", number, name, sizeof(name)); | ||
104 | registerBatteryChargeDesign(number, sm); | 123 | registerBatteryCharge(name, number, sm); | ||
105 | registerBatteryRate(number, sm); | 124 | registerBatteryChargeDesign(name, number, sm); | ||
125 | registerBatteryEnergy(name, number, sm); | ||||
126 | registerBatteryEnergyDesign(name, number, sm); | ||||
127 | registerBatteryRate(name, number, sm); | ||||
128 | registerBatteryRatePower(name, number, sm); | ||||
106 | } | 129 | } | ||
107 | } | 130 | } | ||
108 | closedir( d ); | 131 | closedir( d ); | ||
109 | } | 132 | } | ||
110 | } | 133 | } | ||
111 | 134 | | |||
112 | void printSysBatteryCharge(const char *cmd) | 135 | void printSysBatteryCharge(const char *cmd) | ||
113 | { | 136 | { | ||
114 | int zone = 0; | 137 | int zone = 0; | ||
115 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | 138 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | ||
116 | output("-1\n"); | 139 | output("-1\n"); | ||
117 | return; | 140 | return; | ||
118 | } | 141 | } | ||
119 | 142 | | |||
120 | int charge = getSysFileValue("power_supply", "BAT", zone, "charge_now"); | 143 | int charge = getSysFileValue("power_supply", "BAT", zone, "charge_now"); | ||
121 | int maximum = getSysFileValue("power_supply", "BAT", zone, "charge_full"); | 144 | int maximum = getSysFileValue("power_supply", "BAT", zone, "charge_full"); | ||
122 | int state = 0; | 145 | float state = 0; | ||
123 | if ( maximum > 0) { | 146 | if ( maximum > 0) { | ||
124 | state = charge * 100 / maximum; | 147 | state = charge/(float)(maximum/100);/* to get 0.1% changes */ | ||
You cast to double but then store it in a float, which implies a cast to float. Probably better to just cast to float directly. (Also applies to the functions below.) ahiemstra: You cast to double but then store it in a float, which implies a cast to float. Probably better… | |||||
(float)(var_int/var_int) does not what you want, it should be ((float)var_int / var_int) anthonyfieroni: `(float)(var_int/var_int)` does not what you want, it should be `((float)var_int / var_int)` | |||||
125 | } | 148 | } | ||
126 | if (state > 100) { | 149 | if (state > 100) { | ||
127 | state = 100; /* prevent insane numbers with bad hardware */ | 150 | state = 100; /* prevent insane numbers with bad hardware */ | ||
128 | } else if (state < 0) { | 151 | } else if (state < 0) { | ||
129 | state = 0; /* prevent insane numbers with bad hardware */ | 152 | state = 0; /* prevent insane numbers with bad hardware */ | ||
130 | } | 153 | } | ||
131 | output( "%d\n", state); | 154 | output( "%f\n", state); | ||
132 | } | 155 | } | ||
133 | 156 | | |||
134 | void printSysBatteryChargeInfo(const char *cmd) | 157 | void printSysBatteryChargeInfo(const char *cmd) | ||
135 | { | 158 | { | ||
136 | char name [ 200 ]; | 159 | char name [ 200 ]; | ||
137 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | 160 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | ||
138 | output( "%s charge\t0\t100\t%%\n", name); | 161 | output( "%s charge\t0\t100\t%%\n", name); | ||
139 | } else { | 162 | } else { | ||
140 | output( "Current charge\t0\t100\t%%\n"); | 163 | output( "Current charge\t0\t100\t%%\n"); | ||
141 | } | 164 | } | ||
142 | } | 165 | } | ||
143 | 166 | | |||
144 | void printSysBatteryChargeDesign(const char *cmd) | 167 | void printSysBatteryChargeDesign(const char *cmd) | ||
145 | { | 168 | { | ||
146 | int zone = 0; | 169 | int zone = 0; | ||
147 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | 170 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | ||
148 | output("-1\n"); | 171 | output("-1\n"); | ||
149 | return; | 172 | return; | ||
150 | } | 173 | } | ||
151 | 174 | | |||
152 | int charge = getSysFileValue("power_supply", "BAT", zone, "charge_now"); | 175 | int charge = getSysFileValue("power_supply", "BAT", zone, "charge_now"); | ||
153 | int maximum = getSysFileValue("power_supply", "BAT", zone, "charge_full_design"); | 176 | int maximum = getSysFileValue("power_supply", "BAT", zone, "charge_full_design"); | ||
154 | int state = 0; | 177 | float state = 0; | ||
155 | if (maximum > 0) { | 178 | if (maximum > 0) { | ||
156 | state = charge * 100 / maximum; | 179 | state = charge/(float)(maximum/100);/* to get 0.1% changes */ | ||
anthonyfieroni: ditto | |||||
157 | } | 180 | } | ||
158 | if (state > 100) { | 181 | if (state > 100) { | ||
159 | state = 100; /* prevent insane numbers with bad hardware */ | 182 | state = 100; /* prevent insane numbers with bad hardware */ | ||
160 | } else if (state < 0) { | 183 | } else if (state < 0) { | ||
161 | state = 0; /* prevent insane numbers with bad hardware */ | 184 | state = 0; /* prevent insane numbers with bad hardware */ | ||
162 | } | 185 | } | ||
163 | output( "%d\n", state); | 186 | output( "%f\n", state); | ||
164 | } | 187 | } | ||
165 | 188 | | |||
166 | void printSysBatteryChargeDesignInfo(const char *cmd) | 189 | void printSysBatteryChargeDesignInfo(const char *cmd) | ||
167 | { | 190 | { | ||
168 | char name [ 200 ]; | 191 | char name [ 200 ]; | ||
169 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | 192 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | ||
170 | output( "%s charge (by design)\t0\t100\t%%\n", name); | 193 | output( "%s charge (by design)\t0\t100\t%%\n", name); | ||
171 | } else { | 194 | } else { | ||
172 | output( "Current charge (by design)\t0\t100\t%%\n"); | 195 | output( "Current charge (by design)\t0\t100\t%%\n"); | ||
173 | } | 196 | } | ||
174 | } | 197 | } | ||
175 | 198 | | |||
199 | void printSysBatteryEnergy(const char *cmd) | ||||
200 | { | ||||
201 | int zone = 0; | ||||
202 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | ||||
203 | output("-1\n"); | ||||
204 | return; | ||||
205 | } | ||||
206 | | ||||
207 | int charge = getSysFileValue("power_supply", "BAT", zone, "energy_now"); | ||||
208 | int maximum = getSysFileValue("power_supply", "BAT", zone, "energy_full"); | ||||
209 | float state = 0; | ||||
210 | if ( maximum > 0) { | ||||
211 | state = charge/(float)(maximum/100);/* to get 0.1% changes */ | ||||
anthonyfieroni: ditto | |||||
212 | } | ||||
213 | if (state > 100) { | ||||
214 | state = 100; /* prevent insane numbers with bad hardware */ | ||||
215 | } else if (state < 0) { | ||||
216 | state = 0; /* prevent insane numbers with bad hardware */ | ||||
217 | } | ||||
218 | output( "%f\n", state); | ||||
219 | } | ||||
220 | | ||||
221 | void printSysBatteryEnergyInfo(const char *cmd) | ||||
222 | { | ||||
223 | char name [ 200 ]; | ||||
224 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | ||||
225 | output( "%s energy\t0\t100\t%%\n", name); | ||||
226 | } else { | ||||
227 | output( "Current energy\t0\t100\t%%\n"); | ||||
228 | } | ||||
229 | } | ||||
230 | | ||||
231 | void printSysBatteryEnergyDesign(const char *cmd) | ||||
232 | { | ||||
233 | int zone = 0; | ||||
234 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | ||||
235 | output("-1\n"); | ||||
236 | return; | ||||
237 | } | ||||
238 | | ||||
239 | int charge = getSysFileValue("power_supply", "BAT", zone, "energy_now"); | ||||
240 | int maximum = getSysFileValue("power_supply", "BAT", zone, "energy_full_design"); | ||||
241 | float state = 0; | ||||
242 | if (maximum > 0) { | ||||
243 | state = charge/(float)(maximum/100);/* to get 0.1% changes */ | ||||
anthonyfieroni: ditto | |||||
244 | } | ||||
245 | if (state > 100) { | ||||
246 | state = 100; /* prevent insane numbers with bad hardware */ | ||||
247 | } else if (state < 0) { | ||||
248 | state = 0; /* prevent insane numbers with bad hardware */ | ||||
249 | } | ||||
250 | output( "%f\n", state); | ||||
251 | } | ||||
252 | | ||||
253 | void printSysBatteryEnergyDesignInfo(const char *cmd) | ||||
254 | { | ||||
255 | char name [ 200 ]; | ||||
256 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | ||||
257 | output( "%s energy (by design)\t0\t100\t%%\n", name); | ||||
258 | } else { | ||||
259 | output( "Current energy (by design)\t0\t100\t%%\n"); | ||||
260 | } | ||||
261 | } | ||||
262 | | ||||
176 | void printSysBatteryRate(const char *cmd) | 263 | void printSysBatteryRate(const char *cmd) | ||
177 | { | 264 | { | ||
178 | int zone = 0; | 265 | int zone = 0; | ||
179 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | 266 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | ||
180 | output("-1\n"); | 267 | output("-1\n"); | ||
181 | return; | 268 | return; | ||
182 | } | 269 | } | ||
183 | 270 | | |||
184 | output( "%d\n", getSysFileValue("power_supply", "BAT", zone, "current_now") / 1000); | 271 | output( "%d\n", getSysFileValue("power_supply", "BAT", zone, "current_now") / 1000); | ||
185 | } | 272 | } | ||
186 | 273 | | |||
187 | void printSysBatteryRateInfo(const char *cmd) | 274 | void printSysBatteryRateInfo(const char *cmd) | ||
188 | { | 275 | { | ||
189 | char name [ 200 ]; | 276 | char name [ 200 ]; | ||
190 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | 277 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | ||
191 | output( "%s rate\t0\t0\tmA\n", name); | 278 | output( "%s rate\t0\t0\tmA\n", name); | ||
192 | } else { | 279 | } else { | ||
193 | output( "Current rate\t0\t0\tmA\n"); | 280 | output( "Current rate\t0\t0\tmA\n"); | ||
194 | } | 281 | } | ||
195 | } | 282 | } | ||
196 | 283 | | |||
284 | void printSysBatteryRatePower(const char *cmd) | ||||
285 | { | ||||
286 | int zone = 0; | ||||
287 | if (sscanf(cmd, "acpi/Battery/%d", &zone) <= 0) { | ||||
288 | output("-1\n"); | ||||
289 | return; | ||||
290 | } | ||||
291 | | ||||
292 | output( "%d\n", getSysFileValue("power_supply", "BAT", zone, "power_now") / 1000); | ||||
293 | } | ||||
294 | | ||||
295 | void printSysBatteryRatePowerInfo(const char *cmd) | ||||
296 | { | ||||
297 | char name [ 200 ]; | ||||
298 | if (sscanf(cmd, "acpi/Battery/%199[^/]", name) > 0) { | ||||
299 | output( "%s rate\t0\t0\tmA\n", name); | ||||
300 | } else { | ||||
301 | output( "Current power rate\t0\t0\tmA\n"); | ||||
302 | } | ||||
303 | } | ||||
304 | | ||||
197 | 305 | | |||
198 | /************** ACPI Thermal *****************/ | 306 | /************** ACPI Thermal *****************/ | ||
199 | 307 | | |||
200 | #define OLD_THERMAL_ZONE_DIR "/proc/acpi/thermal_zone" | 308 | #define OLD_THERMAL_ZONE_DIR "/proc/acpi/thermal_zone" | ||
201 | #define OLD_TEMPERATURE_FILE "temperature" | 309 | #define OLD_TEMPERATURE_FILE "temperature" | ||
202 | #define OLD_TEMPERATURE_FILE_MAXLEN 255 | 310 | #define OLD_TEMPERATURE_FILE_MAXLEN 255 | ||
203 | 311 | | |||
204 | #define OLD_FAN_DIR "/proc/acpi/fan" | 312 | #define OLD_FAN_DIR "/proc/acpi/fan" | ||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Line(s) | |||||
334 | 442 | | |||
335 | static int getSysFileValue(const char *className, const char *group, int value, const char *file) { | 443 | static int getSysFileValue(const char *className, const char *group, int value, const char *file) { | ||
336 | static int shownError = 0; | 444 | static int shownError = 0; | ||
337 | char th_file[ ACPIFILENAMELENGTHMAX ]; | 445 | char th_file[ ACPIFILENAMELENGTHMAX ]; | ||
338 | char input_buf[ 100 ]; | 446 | char input_buf[ 100 ]; | ||
339 | snprintf(th_file, sizeof(th_file), "/sys/class/%s/%s%d/%s", className, group, value, file); | 447 | snprintf(th_file, sizeof(th_file), "/sys/class/%s/%s%d/%s", className, group, value, file); | ||
340 | int fd = open(th_file, O_RDONLY); | 448 | int fd = open(th_file, O_RDONLY); | ||
341 | if (fd < 0) { | 449 | if (fd < 0) { | ||
342 | if (!shownError) | 450 | return -1;/* ignore failures, as sys files disappear when battery is removed */ | ||
343 | print_error( "Cannot open file \'%s\'!\n" | | |||
344 | "Load the thermal ACPI kernel module or\n" | | |||
345 | "compile it into your kernel.\n", th_file ); | | |||
346 | shownError = 1; | | |||
347 | return -1; | | |||
348 | } | 451 | } | ||
349 | int read_bytes = read( fd, input_buf, sizeof(input_buf) - 1 ); | 452 | int read_bytes = read( fd, input_buf, sizeof(input_buf) - 1 ); | ||
350 | if ( read_bytes == sizeof(input_buf) - 1 ) { | 453 | if ( read_bytes == sizeof(input_buf) - 1 ) { | ||
351 | if (!shownError) | 454 | if (!shownError) | ||
352 | log_error( "Internal buffer too small to read \'%s\'", th_file ); | 455 | log_error( "Internal buffer too small to read \'%s\'", th_file ); | ||
353 | shownError = 1; | 456 | shownError = 1; | ||
354 | close( fd ); | 457 | close( fd ); | ||
355 | return -1; | 458 | return -1; | ||
▲ Show 20 Lines • Show All 160 Lines • Show Last 20 Lines |
Uhm, this should be const char *name right? I don't really see how this can work otherwise.