Removed various signed comparision warnings
[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.13 2005/03/10 07:01:48 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 /* APM related stuff */
54
55 #define APM_PROC "/proc/apm"
56
57 struct linux_apm_info
58 {
59   char driver_version[10];
60   int apm_version_major;
61   int apm_version_minor;
62   int apm_flags;
63   int ac_line_status;
64   int battery_status;
65   int battery_flags;
66   int battery_percentage;
67   int battery_time;
68   int using_minutes;
69 };
70
71
72 /* ACPI related stuff */
73
74 #define ACPI_PROC "/proc/acpi/info"
75
76 const static char * acpi_info[] = 
77   {
78     "/proc/acpi/battery/0/info",
79     "/proc/acpi/battery/1/info",
80     "/proc/acpi/battery/BATA/info",
81     "/proc/acpi/battery/BAT0/info",
82     "/proc/acpi/battery/BAT1/info" 
83   };
84
85 const static char * acpi_state[] =
86   {    
87     "/proc/acpi/battery/0/status",
88     "/proc/acpi/battery/1/status",
89     "/proc/acpi/battery/BATA/state",
90     "/proc/acpi/battery/BAT0/state",
91     "/proc/acpi/battery/BAT1/state" 
92   };
93
94
95 #define ACPI_BT_CNT  (sizeof(acpi_state) / sizeof(char *))
96
97
98 const static char * acpi_ac[] = 
99   {    
100     "/proc/acpi/ac_adapter/0/status",
101     "/proc/acpi/ac_adapter/AC/state",
102     "/proc/acpi/ac_adapter/ACAD/state" 
103   };
104
105 #define ACPI_AC_CNT  (sizeof(acpi_ac) / sizeof(char *))
106
107
108 #define USE_APM    1
109 #define USE_ACPI   2
110
111 static int method, fd_index;
112
113 /* Prototypes */
114
115 static int
116 apm_read_apm(struct olsr_apm_info *);
117
118 static int
119 apm_read_acpi(struct olsr_apm_info *);
120
121 static int
122 acpi_probe(void);
123
124
125 int 
126 apm_init()
127 {
128   struct olsr_apm_info ainfo;
129
130   method = -1;
131   OLSR_PRINTF(3, "Initializing APM\n")
132
133   if(((fd_index = acpi_probe()) >= 0) && apm_read_acpi(&ainfo))
134     method = USE_ACPI;
135   else if(apm_read_apm(&ainfo))
136     method = USE_APM;
137   
138   if(method)
139     apm_printinfo(&ainfo);
140
141   return method;
142 }
143
144 void
145 apm_printinfo(struct olsr_apm_info *ainfo)
146 {
147   OLSR_PRINTF(5, "APM info:\n\tAC status %d\n\tBattery percentage %d%%\n\n",
148               ainfo->ac_line_status,
149               ainfo->battery_percentage)
150
151   return;
152 }
153
154
155
156 int
157 apm_read(struct olsr_apm_info *ainfo)
158 {
159
160   switch(method)
161     {
162     case(USE_APM):
163       return apm_read_apm(ainfo);
164       break;
165     case(USE_ACPI):
166       return apm_read_acpi(ainfo);
167       break;
168     default:
169       return 0;
170       break;
171     }
172
173   return 1;
174 }
175
176
177
178
179
180 static int
181 apm_read_apm(struct olsr_apm_info *ainfo)
182 {
183   char buffer[100];
184   char units[10];
185   FILE *apm_procfile;
186   struct linux_apm_info lainfo;
187
188   /* Open procfile */
189   if((apm_procfile = fopen(APM_PROC, "r")) == NULL)
190     return 0;
191
192
193   fgets(buffer, sizeof(buffer) - 1, apm_procfile);
194   if(buffer == NULL)
195     {
196       /* Try re-opening the file */
197       if((apm_procfile = fopen(APM_PROC, "r")) < 0)
198         return 0;
199       fgets(buffer, sizeof(buffer) - 1, apm_procfile);
200       if(buffer == NULL)
201         {
202           /* Giving up */
203           fprintf(stderr, "OLSRD: Could not read APM info - setting willingness to default");
204           fclose(apm_procfile);
205           return 0;
206         }
207     }
208
209   buffer[sizeof(buffer) - 1] = '\0';
210
211   //printf("READ: %s\n", buffer);
212
213   /* Get the info */
214   sscanf(buffer, "%s %d.%d %x %x %x %x %d%% %d %s\n",
215          lainfo.driver_version,
216          &lainfo.apm_version_major,
217          &lainfo.apm_version_minor,
218          &lainfo.apm_flags,
219          &lainfo.ac_line_status,
220          &lainfo.battery_status,
221          &lainfo.battery_flags,
222          &lainfo.battery_percentage,
223          &lainfo.battery_time,
224          units);
225
226   lainfo.using_minutes = !strncmp(units, "min", 3) ? 1 : 0;
227
228   /*
229    * Should take care of old APM type info here
230    */
231
232   /*
233    * Fix possible percentage error
234    */
235   if(lainfo.battery_percentage > 100)
236     lainfo.battery_percentage = -1;
237
238   /* Fill the provided struct */
239
240   if(lainfo.ac_line_status)
241     ainfo->ac_line_status = OLSR_AC_POWERED;
242   else
243     ainfo->ac_line_status = OLSR_BATTERY_POWERED;
244   
245   ainfo->battery_percentage = lainfo.battery_percentage;
246   
247   fclose(apm_procfile);
248
249   return 1;
250 }
251
252
253
254 static int
255 apm_read_acpi(struct olsr_apm_info *ainfo)
256 {
257   FILE *fd;
258   char s1[32], s2[32], s3[32], s4[32], inbuff[127];
259   int bat_max = 5000; /* Find some sane value */
260   int bat_val = 0;
261   
262   printf("READING ACPI\n");
263
264
265   if(fd_index < 0)
266     {
267       /* No battery was found or AC power was detected */
268       ainfo->ac_line_status = OLSR_AC_POWERED;
269       ainfo->battery_percentage = 100;
270       return 1;
271     }
272
273
274   /* Get maxvalue */
275   if((fd = fopen(acpi_info[fd_index], "r")) == NULL) 
276     return 0;
277
278   fgets(inbuff, 127, fd);
279   while(!feof(fd)) 
280     {
281       sscanf(inbuff, "%s %s %s %s", s1, s2, s3, s4);
282         
283       if (!strcasecmp(s2, "full")) 
284         {
285           bat_max = atoi(s4);
286         }
287
288       fgets(inbuff, 127, fd);
289     }
290   fclose(fd);
291
292
293   if((fd = fopen(acpi_state[fd_index], "r")) == NULL) 
294     return 0;
295
296   /* Extract battery status */
297   fgets(inbuff, 127, fd);
298   while(!feof(fd)) 
299     {
300       sscanf(inbuff, "%s %s %s %s", s1, s2, s3, s4);
301
302       /* find remaining juice */
303       if(!strcasecmp(s1, "Remaining")) 
304         {
305           bat_val = atoi(s3);
306         }
307
308       fgets(inbuff, 127, fd);
309     }
310
311   fclose(fd);
312
313
314   ainfo->ac_line_status = OLSR_BATTERY_POWERED;
315   ainfo->battery_percentage = bat_val * 100 / bat_max;
316
317   return 1;
318 }
319
320
321
322 static int
323 acpi_probe()
324 {
325   char s1[32], s2[32];
326   FILE *fd;
327   olsr_u16_t i;
328   
329
330   /* First check for AC power */
331
332   for(i = 0; i < ACPI_AC_CNT; i++)
333     {
334       /* Try opening the info file */
335       if((fd = fopen(acpi_ac[i], "r")) == NULL)
336         continue;
337       
338       /* Extract info */
339       if(fscanf(fd, "%s %s", s1, s2) < 2)
340         {
341           fclose(fd);
342           continue;
343         }
344       
345       /* Close info entry */
346       fclose(fd);
347
348       /* Running on AC power */
349       if(!strcasecmp(s2, "on-line"))
350         return -1;
351
352     }
353
354   /* Only checking the first found batery entry... */
355   for(i = 0; i < ACPI_BT_CNT; i ++)
356     {
357
358       /* Try opening the info file */
359       if((fd = fopen(acpi_info[i], "r")) == NULL)
360         continue;
361
362       /* Extract info */
363       if(fscanf(fd, "%s %s", s1, s2) < 2)
364         {
365           fclose(fd);
366           continue;
367         }
368
369       /* Close info entry */
370       fclose(fd);
371
372       /* Check if battery is present */
373       if((!strcasecmp(s1, "present:")) && (!strcasecmp(s2, "no"))) 
374         continue;
375
376       /* Open the corresponding state file */
377       if((fd = fopen(acpi_state[i], "r")) == NULL)
378         continue;
379
380       fclose(fd);
381
382       return i;
383     }
384
385   /* No battery found */
386   return -1;
387 }
388