Mass update FSF address
[dockapps.git] / wmpower / src / power_management / acpi / libacpi.c
blob8291e0b9510ade8a3e57471a063dbd8c33b5c9c0
1 /***************************************************************************
2 libacpi.c - description
3 -------------------
4 begin : Feb 10 2003
5 copyright : (C) 2003 by Noberasco Michele
6 e-mail : 2001s098@educ.disi.unige.it
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
25 * *
26 ***************************************************************************/
28 /***************************************************************************
29 Originally written by Costantino Pistagna for his wmacpimon
30 ***************************************************************************/
33 #ifndef _GNU_SOURCE
34 #define _GNU_SOURCE
35 #endif
37 #include <stdio.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <dirent.h>
43 #include <ctype.h>
45 #include "libacpi.h"
46 #include "power_management.h"
47 #include "lib_utils.h"
50 /* here we put temp stuff read from proc files */
51 char buf[512];
53 static char batteries[MAXBATT][128];
54 static char battinfo[MAXBATT][128];
55 static char fans[MAXFANS][128];
58 void sort(char names[MAXBATT][128], int count)
60 int i, j;
61 char temp[128];
63 for (i=0; i<(count-1); i++)
64 for (j=i+1; j<count; j++)
65 if (strcmp(names[j], names[i]) < 0)
67 strcpy(temp, names[j]);
68 strcpy(names[j], names[i]);
69 strcpy(names[i], temp);
73 /* see if we have ACPI support */
74 int check_acpi(void)
76 DIR *battdir;
77 struct dirent *batt;
78 char *name;
80 /* do proc entries for acpi exist? */
81 if (access("/proc/acpi/info", R_OK) != 0) return 0;
83 /* now enumerate batteries */
84 batt_count = 0;
85 battdir = opendir ("/proc/acpi/battery");
86 if (!battdir) return 0;
88 while ((batt = readdir (battdir)))
90 name = batt->d_name;
92 /* skip . and .. */
93 if (!strcmp (".", name) || !strcmp ("..", name)) continue;
95 if (!access("/proc/acpi/battery/1/status", R_OK))
96 sprintf (batteries[batt_count], "/proc/acpi/battery/%s/status", name);
97 else
98 sprintf (batteries[batt_count], "/proc/acpi/battery/%s/state", name);
99 sprintf (battinfo[batt_count], "/proc/acpi/battery/%s/info", name);
101 batt_count++;
103 closedir (battdir);
105 /* order battery names as readdir doesn't handle that */
106 if (batt_count > 1)
108 sort(batteries, batt_count);
109 sort(battinfo, batt_count);
112 fprintf(stderr, "libacpi: found %d batter%s\n", batt_count, (batt_count == 1) ? "y" : "ies");
114 return 1;
118 char *find_acad_proc_file(void)
120 DIR *dir;
121 char *basedir = "/proc/acpi/ac_adapter/";
122 struct dirent *entry;
124 dir= opendir(basedir);
125 if (!dir) return NULL;
127 while ((entry= readdir(dir)))
129 char *result = NULL;
130 char *temp1, *temp2, *temp3;
131 if (!strcmp(entry->d_name, "." )) continue;
132 if (!strcmp(entry->d_name, "..")) continue;
133 temp1 = StrApp((char**)NULL, basedir, entry->d_name, "/state", (char*)NULL);
134 temp2 = StrApp((char**)NULL, basedir, entry->d_name, "/status", (char*)NULL);
135 temp3 = StrApp((char**)NULL, basedir, entry->d_name, "/stats", (char*)NULL);
137 if (!access(temp1, R_OK)) {result = temp1; free(temp2); free(temp3);}
138 else if (!access(temp2, R_OK)) {result = temp2; free(temp1); free(temp3);}
139 else if (!access(temp3, R_OK)) {result = temp3; free(temp1); free(temp2);}
141 if (result)
143 closedir(dir);
144 return result;
146 free(temp1); free(temp2); free(temp3);
148 closedir(dir);
150 return NULL;
153 void read_acad_state (ACADstate *acadstate)
155 static int searched = 0;
156 static char *file = NULL;
157 static char *where = NULL;
158 FILE *fp;
160 if (!searched)
162 file = find_acad_proc_file();
163 searched = 1;
165 if (!file) return;
166 if (!(fp = fopen(file, "r"))) return;
168 fread_unlocked (buf, 512, 1, fp);
169 fclose(fp);
171 if (!where)
173 if (!strncmp(buf, "state:", 6)) where = buf + 26;
174 if (!strncmp(buf, "Status:", 7)) where = buf + 26;
176 if (!where) return;
178 if (where[0] == 'n') acadstate->state = 1;
179 if (where[0] == 'f') acadstate->state = 0;
183 void read_acpi_info (ACPIinfo *acpiinfo, int battery)
185 FILE *fp;
186 char *ptr = buf;
187 int offset = 25;
189 if (battery > MAXBATT) return;
190 if (!(fp = fopen (battinfo[battery], "r"))) return;
192 fread_unlocked (buf, 512, 1, fp);
193 fclose(fp);
195 while (ptr)
197 static int count = 0;
199 if (!strncmp(ptr+1, "resent:", 7))
201 if (ptr[offset] != 'y')
203 acpiinfo->present = 0;
204 acpiinfo->design_capacity = 0;
205 acpiinfo->last_full_capacity = 0;
206 acpiinfo->battery_technology = 0;
207 acpiinfo->design_voltage = 0;
208 acpiinfo->design_capacity_warning = 0;
209 acpiinfo->design_capacity_low = 0;
210 return;
212 acpiinfo->present = 1;
213 ptr = jump_next_line(ptr);
214 if (!ptr) break;
216 if (!strncmp(ptr, "design capacity:", 16) || !strncmp(ptr, "Design Capacity:", 16))
218 sscanf (ptr+offset, "%d", &(acpiinfo->design_capacity));
219 ptr = jump_next_line(ptr);
220 if (!ptr) break;
222 if (!strncmp(ptr, "last full capacity:", 19) || !strncmp(ptr, "Last Full Capacity:", 19))
224 sscanf (ptr+offset, "%d", &(acpiinfo->last_full_capacity));
225 ptr = jump_next_line(ptr);
226 if (!ptr) break;
228 if (!strncmp(ptr, "battery technology:", 19) || !strncmp(ptr, "Battery Technology:", 19))
230 switch (ptr[offset])
232 case 'n':
233 acpiinfo->battery_technology = 1;
234 break;
235 case 'r':
236 acpiinfo->battery_technology = 0;
237 break;
239 ptr = jump_next_line(ptr);
240 if (!ptr) break;
242 if (!strncmp(ptr, "design voltage:", 15) || !strncmp(ptr, "Design Voltage:", 15))
244 sscanf (ptr+offset, "%d", &(acpiinfo->design_voltage ));
245 ptr = jump_next_line(ptr);
246 if (!ptr) break;
248 if (!strncmp(ptr, "design capacity warning:", 24) || !strncmp(ptr, "Design Capacity Warning:", 24))
250 sscanf (ptr+offset, "%d", &(acpiinfo->design_capacity_warning));
251 ptr = jump_next_line(ptr);
252 if (!ptr) break;
254 if (!strncmp(ptr, "design capacity low:", 20) || !strncmp(ptr, "Design Capacity Low:", 20))
256 sscanf (ptr+offset, "%d", &(acpiinfo->design_capacity_low));
257 if (!count) return; /* we did read all stuff in just one passage! */
258 ptr = jump_next_line(ptr);
259 if (!ptr) break;
262 ptr = jump_next_line(ptr);
263 count++;
268 void read_acpi_state (ACPIstate *acpistate, ACPIinfo *acpiinfo, int battery)
270 FILE *fp;
271 char *ptr = buf;
272 int offset = 25;
274 if (battery > MAXBATT) return;
275 if (!(fp = fopen (batteries[battery], "r"))) return;
277 fread_unlocked (buf, 512, 1, fp);
278 fclose(fp);
280 while (ptr)
282 static int count = 0;
284 if (!strncmp(ptr+1, "resent:", 7))
286 if (ptr[offset] != 'y')
288 acpistate->present = 0;
289 acpistate->state = UNKNOW;
290 acpistate->prate = 0;
291 acpistate->rcapacity = 0;
292 acpistate->pvoltage = 0;
293 acpistate->rtime = 0;
294 acpistate->percentage = 0;
296 return;
298 acpistate->present = 1;
299 ptr = jump_next_line(ptr);
300 if (!ptr) return;
302 if (!strncmp(ptr, "capacity state:", 15))
304 /* nothing to do here... */
305 ptr = jump_next_line(ptr);
306 if (!ptr) return;
308 if (!strncmp(ptr, "charging state:", 15) || !strncmp(ptr, "State:", 6))
310 switch (ptr[offset])
312 case 'd':
313 acpistate->state = 1;
314 break;
315 case 'c':
317 if (*(ptr + 33) == '/') acpistate->state = 0;
318 if (!strncmp(ptr+offset, "charged", 7))
319 acpistate->state = 1;
320 else
321 acpistate->state = 2;
322 break;
324 case 'u':
325 acpistate->state = 3;
326 break;
328 ptr = jump_next_line(ptr);
329 if (!ptr) return;
331 if (!strncmp(ptr, "present rate:", 13) || !strncmp(ptr, "Present Rate:", 13))
333 sscanf (ptr+offset, "%d", &(acpistate->prate));
334 /* if something wrong */
335 if (acpistate->prate <= 0) acpistate->prate = 0;
336 ptr = jump_next_line(ptr);
337 if (!ptr) return;
339 if (!strncmp(ptr, "remaining capacity:", 19) || !strncmp(ptr, "Remaining Capacity:", 19))
341 sscanf (ptr+offset, "%d", &(acpistate->rcapacity));
342 acpistate->percentage = (float) ((float) acpistate->rcapacity / (float) acpiinfo->last_full_capacity) * 100;
343 ptr = jump_next_line(ptr);
344 if (!ptr) return;
346 if (!strncmp(ptr, "present voltage:", 16) || !strncmp(ptr, "Battery Voltage:", 16))
348 sscanf (ptr+offset, "%d", &(acpistate->pvoltage));
349 if (!count) break; /* we did read all stuff in just one passage! */
350 ptr = jump_next_line(ptr);
351 if (!ptr) return;
354 ptr = jump_next_line(ptr);
355 count++;
358 /* time remaining in minutes */
359 if (!acpistate->prate) return;
360 if (acpistate->state == 2) /* charging */
361 acpistate->rtime = ((float) ((float) (acpiinfo->last_full_capacity - acpistate->rcapacity) / (float) acpistate->prate)) * 60;
362 else /* discharging */
363 acpistate->rtime = ((float) ((float) acpistate->rcapacity / (float) acpistate->prate)) * 60;
364 if (acpistate->rtime <= 0) acpistate->rtime = 0;
367 char *find_temperature_proc_file(void)
369 DIR *dir;
370 char *basedir = "/proc/acpi/thermal_zone/";
371 struct dirent *entry;
373 dir= opendir(basedir);
374 if (!dir) return NULL;
376 while ((entry= readdir(dir)))
378 char *temp;
379 if (!strcmp(entry->d_name, "." )) continue;
380 if (!strcmp(entry->d_name, "..")) continue;
381 temp = StrApp((char**)NULL, basedir, entry->d_name, "/temperature", (char*)NULL);
382 if (!access(temp, R_OK))
384 closedir(dir);
385 return temp;
387 free(temp);
389 closedir(dir);
391 return NULL;
394 void acpi_get_temperature(int *temperature, int *temp_is_celsius)
396 static int temp;
397 static char unit[2];
398 static int searched = 0;
399 static char *file = NULL;
400 FILE *fp;
402 (*temperature) = PM_Error;
403 (*temp_is_celsius) = PM_Error;
405 if (!searched)
407 file = find_temperature_proc_file();
408 searched = 1;
410 if (!file) return;
411 if (!(fp=fopen(file, "r"))) return;
412 if (!fgets(buf, 512, fp))
414 fclose(fp);
415 return;
417 fclose(fp);
419 if (sscanf(buf, "%*s%d%1s", &temp, unit) != 2) return;
421 (*temperature) = temp;
422 if (*unit == 'C') (*temp_is_celsius) = 1;
423 else (*temp_is_celsius) = 0;
426 int get_fan_info(void)
428 struct dirent *entry;
429 char *basedir = "/proc/acpi/fan";
430 DIR *dir;
431 int n_fans = 0;
433 dir = opendir(basedir);
434 if (!dir) return 0;
435 while ((entry= readdir(dir)))
437 char *temp;
438 if (!strcmp(entry->d_name, "." )) continue;
439 if (!strcmp(entry->d_name, "..")) continue;
440 temp = StrApp((char**)NULL, basedir, "/", entry->d_name, "/state", (char*)NULL);
441 if (!access(temp, R_OK))
443 if (n_fans == MAXFANS)
445 fprintf(stderr, "acpi_lib: found more fans, but wmpower can handle only %d.\n", MAXFANS);
446 free(temp);
447 break;
449 strncpy(fans[n_fans], temp, 127);
450 fans[n_fans][127] = '\0';
451 n_fans++;
452 fprintf(stderr, "acpi_lib: found fan info at '%s'\n", temp);
454 else fprintf(stderr, "acpi_lib: cannot access fan info at '%s'\n", temp);
455 free(temp);
457 closedir(dir);
458 fprintf(stderr, "acpi_lib: %d fan(s) found...\n", n_fans);
460 return n_fans;
463 /* return number of fans running */
464 int acpi_get_fan_status(void)
466 static int n_fans = -1;
467 int running_fans = 0;
468 int i;
470 if (n_fans == -1) n_fans = get_fan_info();
471 if (!n_fans) return PM_Error;
473 for (i=0; i<n_fans; i++)
475 char *ptr = buf;
476 FILE *fp = fopen(fans[i], "r");
477 int offset = 26;
479 if (!fp) return PM_Error;
480 if (!fgets(buf, 512, fp)) ptr = NULL;
481 fclose(fp);
482 if (!ptr) return PM_Error;
483 if (ptr[offset] == 'n') running_fans++;
486 return running_fans;