15 extern APMInfo
*apminfo
;
16 static char batteries
[MAXBATT
][128];
17 static char battinfo
[MAXBATT
][128];
23 int acpi_get_design_cap(int battery
);
25 /* see if we have ACPI support and check version */
35 if (!(acpi
= fopen("/proc/acpi/info", "r"))) {
36 fprintf(stderr
, "This system does not support ACPI\n");
40 /* okay, now see if we got the right version */
41 fread(buf
, 4096, 1, acpi
);
42 acpi_ver
= strtol(buf
+ 25, NULL
, 10);
43 eprint(1, "ACPI version detected: %d\n", acpi_ver
);
44 if (acpi_ver
< 20020214) {
45 fprintf(stderr
, "This version requires ACPI subsystem version 20020214\n");
53 /* now enumerate batteries */
55 battdir
= opendir("/proc/acpi/battery");
56 if (battdir
== NULL
) {
57 fprintf(stderr
, "No batteries or ACPI not supported\n");
60 while ((batt
= readdir(battdir
))) {
64 if (!strncmp(".", name
, 1) || !strncmp("..", name
, 2))
67 sprintf(batteries
[batt_count
], "/proc/acpi/battery/%s/state", name
);
68 sprintf(battinfo
[batt_count
], "/proc/acpi/battery/%s/info", name
);
69 eprint(1, "battery detected at %s\n", batteries
[batt_count
]);
74 /* tell user some info */
75 eprint(1, "%d batteries detected\n", batt_count
);
76 fprintf(stderr
, "wmacpi: found %d batter%s\n", batt_count
,
77 (batt_count
== 1) ? "y" : "ies");
82 int acpi_get_design_cap(int battery
)
88 if (battery
> MAXBATT
)
91 if (!(acpi
= fopen(battinfo
[battery
], "r")))
94 fread(buf
, 512, 1, acpi
);
97 if ((ptr
= strstr(buf
, "last full capacity"))) {
99 sscanf(ptr
, "%d", &design_cap
);
100 eprint(1, "last full capacity: %d\n", design_cap
);
102 /* hack. if there isnt any info on last capacity, we are
103 * screwed, but let's not come back here again */
105 eprint(1, "Cannot retrieve design capacity!");
111 void acquire_info(void)
117 static int dcap
= 0xdeadbeef;
119 int percent
= 100; /* battery percentage */
120 int ptemp
, rate
, rtime
= 0;
122 if (dcap
== 0xdeadbeef) {
123 /* get from first battery for now */
124 dcap
= acpi_get_design_cap(0);
127 if (!(acpi
= fopen(batteries
[0], "r")))
130 eprint(1, "opened acpi file successfully");
131 fread(buf
, 512, 1, acpi
);
134 /* This section of the code will calculate "percentage remaining"
135 * using battery capacity, and the following formula (acpi spec 3.9.2):
136 * percentage = (current_capacity / last_full_capacity) * 100; */
137 if ((ptr
= strstr(buf
, "remaining capacity"))) {
139 sscanf(ptr
, "%d", &ptemp
);
140 eprint(1, "capacity: %d\n", ptemp
);
141 percent
= (float)((float)ptemp
/ (float)dcap
) * 100;
142 eprint(1, "percent: %d\n", percent
);
144 apminfo
->percentage
= percent
;
146 /* this section of code will calculate "time remaining"
147 * using battery remaining capacity, and battery "rate" (3.9.3) */
148 if ((ptr
= strstr(buf
, "present rate"))) {
150 sscanf(ptr
, "%d", &rate
);
151 eprint(1, "rate: %d\n", rate
);
154 /* time remaining in minutes */
155 rtime
= ((float)((float)ptemp
/ (float)rate
)) * 60;
158 eprint(1, "time rem: %d\n", rtime
);
160 apminfo
->rtime
= rtime
;
162 if ((ptr
= strstr(buf
, "charging state"))) {
163 /* found battery discharging. This is used to determine if
164 * we are on AC power or not. Notice check for "ch" later on */
166 if (stat
== 'o' || stat
== 'u') /* "ok" | "unknown" : charged, on ac power */
167 apminfo
->power
= POWER
;
169 /* we set this, and later on use percentage
170 * value to determine high/med/low */
171 apminfo
->power
= HIGH
;
173 /* but if we are on power, we might be charging too. Check. */
174 if ((ptr
= strstr(buf
, "charging state"))) {
175 /* found battery charging line. We will change power state
176 * if we are on power, and charging. */
178 /* this is seriously stupid - but we catch "critical" */
179 if (stat
== 'c' && (*(ptr
+ 26) == 'h'))
180 apminfo
->power
= CHARGING
;
184 /* we are not on power, and not charging. So, it would make sense
185 * to check if battery is "critical low", and calculate interesting
186 * things like battery HIGH/LOW, and maybe battery usage LOAD
187 * This will be replaced with some code to allow setting user-specified
188 * low / critical alarms */
189 if ((apminfo
->power
!= POWER
) && (apminfo
->power
!= CHARGING
)) {
190 eprint(1, "entering battery status check");
191 if ((ptr
= strstr(buf
, "capacity state"))) {
193 /* only check "c" here because we already caught "CHarging" earlier
194 * and also look into crit_level */
195 if (stat
== 'c' || (apminfo
->percentage
<= apminfo
->crit_level
)) {
196 /* nothing else to do here - critical battery. get out */
197 eprint(1, "Received critical battery status");
198 apminfo
->power
= CRIT
;
202 process_plugin_timer();
204 eprint(1, "current state: %s (%d)", state
[apminfo
->power
], apminfo
->power
);