326bd6400d20ac9cafe0d888b17b3ea789f775a4
[olsrd.git] / src / linux / apm.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: apm.c,v 1.11 2005/02/27 10:43:38 kattemat Exp $
40  */
41
42 /*
43  * Much of the ACPI code is taken from Florian Schaefers
44  * Acpi-Power Enlightenment epplet
45  */
46
47 #include "apm.h"
48 #include "defs.h"
49 #include <stdio.h>
50 #include <string.h>
51 #include <stdlib.h>
52
53 #warning ACPI code not tested!!!!
54
55 /* APM related stuff */
56
57 #define APM_PROC "/proc/apm"
58
59 struct linux_apm_info
60 {
61   char driver_version[10];
62   int apm_version_major;
63   int apm_version_minor;
64   int apm_flags;
65   int ac_line_status;
66   int battery_status;
67   int battery_flags;
68   int battery_percentage;
69   int battery_time;
70   int using_minutes;
71 };
72
73
74 /* ACPI related stuff */
75
76 #define ACPI_PROC "/proc/acpi/info"
77
78 const static char * acpi_info[] = 
79   {
80     "/proc/acpi/battery/0/info",
81     "/proc/acpi/battery/1/info",
82     "/proc/acpi/battery/BATA/info",
83     "/proc/acpi/battery/BAT0/info",
84     "/proc/acpi/battery/BAT1/info" 
85   };
86
87 const static char * acpi_state[] =
88   {    
89     "/proc/acpi/battery/0/status",
90     "/proc/acpi/battery/1/status",
91     "/proc/acpi/battery/BATA/state",
92     "/proc/acpi/battery/BAT0/state",
93     "/proc/acpi/battery/BAT1/state" 
94   };
95
96
97 #define ACPI_BT_CNT  (sizeof(acpi_state) / sizeof(char *))
98
99
100 const static char * acpi_ac[] = 
101   {    
102     "/proc/acpi/ac_adapter/0/status",
103     "/proc/acpi/ac_adapter/AC/state",
104     "/proc/acpi/ac_adapter/ACAD/state" 
105   };
106
107 #define ACPI_AC_CNT  (sizeof(acpi_ac) / sizeof(char *))
108
109
110 #define USE_APM    1
111 #define USE_ACPI   2
112
113 static int method, fd_index;
114
115 /* Prototypes */
116
117 static int
118 apm_read_apm(struct olsr_apm_info *);
119
120 static int
121 apm_read_acpi(struct olsr_apm_info *);
122
123 static int
124 acpi_probe(void);
125
126
127 int 
128 apm_init()
129 {
130   struct olsr_apm_info ainfo;
131
132   method = -1;
133   OLSR_PRINTF(3, "Initializing APM\n")
134
135   if(((fd_index = acpi_probe()) >= 0) && apm_read_acpi(&ainfo))
136     method = USE_ACPI;
137   else if(apm_read_apm(&ainfo))
138     method = USE_APM;
139   
140   if(method)
141     apm_printinfo(&ainfo);
142
143   return method;
144 }
145
146 void
147 apm_printinfo(struct olsr_apm_info *ainfo)
148 {
149   OLSR_PRINTF(5, "APM info:\n\tAC status %d\n\tBattery percentage %d%%\n\n",
150               ainfo->ac_line_status,
151               ainfo->battery_percentage)
152
153   return;
154 }
155
156
157
158 int
159 apm_read(struct olsr_apm_info *ainfo)
160 {
161
162   switch(method)
163     {
164     case(USE_APM):
165       return apm_read_apm(ainfo);
166       break;
167     case(USE_ACPI):
168       return apm_read_acpi(ainfo);
169       break;
170     default:
171       return 0;
172       break;
173     }
174
175   return 1;
176 }
177
178
179
180
181
182 static int
183 apm_read_apm(struct olsr_apm_info *ainfo)
184 {
185   char buffer[100];
186   char units[10];
187   FILE *apm_procfile;
188   struct linux_apm_info lainfo;
189
190   /* Open procfile */
191   if((apm_procfile = fopen(APM_PROC, "r")) == NULL)
192     return 0;
193
194
195   fgets(buffer, sizeof(buffer) - 1, apm_procfile);
196   if(buffer == NULL)
197     {
198       /* Try re-opening the file */
199       if((apm_procfile = fopen(APM_PROC, "r")) < 0)
200         return 0;
201       fgets(buffer, sizeof(buffer) - 1, apm_procfile);
202       if(buffer == NULL)
203         {
204           /* Giving up */
205           fprintf(stderr, "OLSRD: Could not read APM info - setting willingness to default");
206           fclose(apm_procfile);
207           return 0;
208         }
209     }
210
211   buffer[sizeof(buffer) - 1] = '\0';
212
213   //printf("READ: %s\n", buffer);
214
215   /* Get the info */
216   sscanf(buffer, "%s %d.%d %x %x %x %x %d%% %d %s\n",
217          lainfo.driver_version,
218          &lainfo.apm_version_major,
219          &lainfo.apm_version_minor,
220          &lainfo.apm_flags,
221          &lainfo.ac_line_status,
222          &lainfo.battery_status,
223          &lainfo.battery_flags,
224          &lainfo.battery_percentage,
225          &lainfo.battery_time,
226          units);
227
228   lainfo.using_minutes = !strncmp(units, "min", 3) ? 1 : 0;
229
230   /*
231    * Should take care of old APM type info here
232    */
233
234   /*
235    * Fix possible percentage error
236    */
237   if(lainfo.battery_percentage > 100)
238     lainfo.battery_percentage = -1;
239
240   /* Fill the provided struct */
241
242   if(lainfo.ac_line_status)
243     ainfo->ac_line_status = OLSR_AC_POWERED;
244   else
245     ainfo->ac_line_status = OLSR_BATTERY_POWERED;
246   
247   ainfo->battery_percentage = lainfo.battery_percentage;
248   
249   fclose(apm_procfile);
250
251   return 1;
252 }
253
254
255
256 static int
257 apm_read_acpi(struct olsr_apm_info *ainfo)
258 {
259   FILE *fd;
260   char s1[32], s2[32], s3[32], s4[32], inbuff[127];
261   int bat_max = 5000; /* Find some sane value */
262   int bat_val = 0;
263   
264   printf("READING ACPI\n");
265
266
267   if(fd_index < 0)
268     {
269       /* No battery was found or AC power was detected */
270       ainfo->ac_line_status = OLSR_AC_POWERED;
271       ainfo->battery_percentage = 100;
272       return 1;
273     }
274
275
276   /* Get maxvalue */
277   if((fd = fopen(acpi_info[fd_index], "r")) == NULL) 
278     return 0;
279
280   fgets(inbuff, 127, fd);
281   while(!feof(fd)) 
282     {
283       sscanf(inbuff, "%s %s %s %s", s1, s2, s3, s4);
284         
285       if (!strcasecmp(s2, "full")) 
286         {
287           bat_max = atoi(s4);
288         }
289
290       fgets(inbuff, 127, fd);
291     }
292   fclose(fd);
293
294
295   if((fd = fopen(acpi_state[fd_index], "r")) == NULL) 
296     return 0;
297
298   /* Extract battery status */
299   fgets(inbuff, 127, fd);
300   while(!feof(fd)) 
301     {
302       sscanf(inbuff, "%s %s %s %s", s1, s2, s3, s4);
303
304       /* find remaining juice */
305       if(!strcasecmp(s1, "Remaining")) 
306         {
307           bat_val = atoi(s3);
308         }
309
310       fgets(inbuff, 127, fd);
311     }
312
313   fclose(fd);
314
315
316   ainfo->ac_line_status = OLSR_BATTERY_POWERED;
317   ainfo->battery_percentage = bat_val * 100 / bat_max;
318
319   return 1;
320 }
321
322
323
324 static int
325 acpi_probe()
326 {
327   char s1[32], s2[32];
328   FILE *fd;
329   int i;
330   
331
332   /* First check for AC power */
333
334   for(i = 0; i < ACPI_AC_CNT; i++)
335     {
336       /* Try opening the info file */
337       if((fd = fopen(acpi_ac[i], "r")) == NULL)
338         continue;
339       
340       /* Extract info */
341       if(fscanf(fd, "%s %s", s1, s2) < 2)
342         {
343           fclose(fd);
344           continue;
345         }
346       
347       /* Close info entry */
348       fclose(fd);
349
350       /* Running on AC power */
351       if(!strcasecmp(s2, "on-line"))
352         return -1;
353
354     }
355
356   /* Only checking the first found batery entry... */
357   for(i = 0; i < ACPI_BT_CNT; i ++)
358     {
359
360       /* Try opening the info file */
361       if((fd = fopen(acpi_info[i], "r")) == NULL)
362         continue;
363
364       /* Extract info */
365       if(fscanf(fd, "%s %s", s1, s2) < 2)
366         {
367           fclose(fd);
368           continue;
369         }
370
371       /* Close info entry */
372       fclose(fd);
373
374       /* Check if battery is present */
375       if((!strcasecmp(s1, "present:")) && (!strcasecmp(s2, "no"))) 
376         continue;
377
378       /* Open the corresponding state file */
379       if((fd = fopen(acpi_state[i], "r")) == NULL)
380         continue;
381
382       fclose(fd);
383
384       return i;
385     }
386
387   /* No battery found */
388   return -1;
389 }
390