]> git.sur5r.net Git - i3/i3status/blob - src/get_battery_info.c
41f2ff36d89731088bf0605068856a6684576eaa
[i3/i3status] / src / get_battery_info.c
1 // vim:ts=8:expandtab
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 #include "i3status.h"
7
8 #if defined(__FreeBSD__)
9 #include <sys/types.h>
10 #include <sys/sysctl.h>
11 #endif
12
13 /*
14  * Get battery information from /sys. Note that it uses the design capacity to
15  * calculate the percentage, not the last full capacity, so you can see how
16  * worn off your battery is.
17  *
18  */
19 const char *get_battery_info(struct battery *bat) {
20         char buf[1024];
21         static char part[512];
22         char *walk, *last;
23         int full_design = -1,
24             remaining = -1,
25             present_rate = -1;
26         charging_status_t status = CS_DISCHARGING;
27
28 #if defined(LINUX)
29         if (!slurp(bat->path, buf, sizeof(buf)))
30                 return "No battery";
31
32         for (walk = buf, last = buf; (walk-buf) < 1024; walk++) {
33                 if (*walk == '\n') {
34                         last = walk+1;
35                         continue;
36                 }
37
38                 if (*walk != '=')
39                         continue;
40
41                 if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW") ||
42                     BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW"))
43                         remaining = atoi(walk+1);
44                 else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW"))
45                         present_rate = atoi(walk+1);
46                 else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging"))
47                         status = CS_CHARGING;
48                 else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full"))
49                         status = CS_FULL;
50                 else {
51                         /* The only thing left is the full capacity */
52                         if (bat->use_last_full) {
53                                 if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") &&
54                                     !BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL"))
55                                         continue;
56                         } else {
57                                 if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") &&
58                                     !BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN"))
59                                         continue;
60                         }
61
62                         full_design = atoi(walk+1);
63                 }
64         }
65
66         if ((full_design == 1) || (remaining == -1))
67                 return part;
68
69         if (present_rate > 0) {
70                 float remaining_time;
71                 int seconds, hours, minutes;
72                 if (status == CS_CHARGING)
73                         remaining_time = ((float)full_design - (float)remaining) / (float)present_rate;
74                 else if (status == CS_DISCHARGING)
75                         remaining_time = ((float)remaining / (float)present_rate);
76                 else remaining_time = 0;
77
78                 seconds = (int)(remaining_time * 3600.0);
79                 hours = seconds / 3600;
80                 seconds -= (hours * 3600);
81                 minutes = seconds / 60;
82                 seconds -= (minutes * 60);
83
84                 (void)snprintf(part, sizeof(part), "%s %.02f%% %02d:%02d:%02d",
85                         (status == CS_CHARGING ? "CHR" :
86                          (status == CS_DISCHARGING ? "BAT" : "FULL")),
87                         (((float)remaining / (float)full_design) * 100),
88                         max(hours, 0), max(minutes, 0), max(seconds, 0));
89         } else {
90                 (void)snprintf(part, sizeof(part), "%s %.02f%%",
91                         (status == CS_CHARGING ? "CHR" :
92                          (status == CS_DISCHARGING ? "BAT" : "FULL")),
93                         (((float)remaining / (float)full_design) * 100));
94         }
95 #elif defined(__FreeBSD__)
96         int state;
97         int sysctl_rslt;
98         size_t sysctl_size = sizeof(sysctl_rslt);
99
100         if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0)
101                 return "No battery";
102
103         present_rate = sysctl_rslt;
104         if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0)
105                 return "No battery";
106
107         remaining = sysctl_rslt;
108         if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0)
109                 return "No battery";
110
111         state = sysctl_rslt;
112         if (state == 0 && present_rate == 100)
113                 status = CS_FULL;
114         else if (state == 0 && present_rate < 100)
115                 status = CS_CHARGING;
116         else
117                 status = CS_DISCHARGING;
118
119         full_design = sysctl_rslt;
120
121         if (state == 1) {
122                 int hours, minutes;
123                 minutes = remaining;
124                 hours = minutes / 60;
125                 minutes -= (hours * 60);
126                 (void)snprintf(part, sizeof(part), "%s %02d%% %02dh%02d",
127                                (status == CS_CHARGING ? "CHR" :
128                                 (status == CS_DISCHARGING ? "BAT" : "FULL")),
129                                present_rate,
130                                max(hours, 0), max(minutes, 0));
131         } else {
132                 (void)snprintf(part, sizeof(part), "%s %02d%%",
133                                (status == CS_CHARGING ? "CHR" :
134                                 (status == CS_DISCHARGING ? "BAT" : "FULL")),
135                                present_rate);
136         }
137 #endif
138         return part;
139 }