]> git.sur5r.net Git - i3/i3status/blob - src/get_battery_info.c
Don’t perror("connect") when there most likely is no IPv6 connectivity
[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         slurp(bat->path, buf, sizeof(buf));
30
31         for (walk = buf, last = buf; (walk-buf) < 1024; walk++) {
32                 if (*walk == '\n') {
33                         last = walk+1;
34                         continue;
35                 }
36
37                 if (*walk != '=')
38                         continue;
39
40                 if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW") ||
41                     BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW"))
42                         remaining = atoi(walk+1);
43                 else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW"))
44                         present_rate = atoi(walk+1);
45                 else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging"))
46                         status = CS_CHARGING;
47                 else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full"))
48                         status = CS_FULL;
49                 else {
50                         /* The only thing left is the full capacity */
51                         if (bat->use_last_full) {
52                                 if (!BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL") &&
53                                     !BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL"))
54                                         continue;
55                         } else {
56                                 if (!BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN") &&
57                                     !BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN"))
58                                         continue;
59                         }
60
61                         full_design = atoi(walk+1);
62                 }
63         }
64
65         if ((full_design == 1) || (remaining == -1))
66                 return part;
67
68         if (present_rate > 0) {
69                 float remaining_time;
70                 int seconds, hours, minutes;
71                 if (status == CS_CHARGING)
72                         remaining_time = ((float)full_design - (float)remaining) / (float)present_rate;
73                 else if (status == CS_DISCHARGING)
74                         remaining_time = ((float)remaining / (float)present_rate);
75                 else remaining_time = 0;
76
77                 seconds = (int)(remaining_time * 3600.0);
78                 hours = seconds / 3600;
79                 seconds -= (hours * 3600);
80                 minutes = seconds / 60;
81                 seconds -= (minutes * 60);
82
83                 (void)snprintf(part, sizeof(part), "%s %.02f%% %02d:%02d:%02d",
84                         (status == CS_CHARGING ? "CHR" :
85                          (status == CS_DISCHARGING ? "BAT" : "FULL")),
86                         (((float)remaining / (float)full_design) * 100),
87                         max(hours, 0), max(minutes, 0), max(seconds, 0));
88         } else {
89                 (void)snprintf(part, sizeof(part), "%s %.02f%%",
90                         (status == CS_CHARGING ? "CHR" :
91                          (status == CS_DISCHARGING ? "BAT" : "FULL")),
92                         (((float)remaining / (float)full_design) * 100));
93         }
94 #elif defined(__FreeBSD__)
95         int state;
96         int sysctl_rslt;
97         size_t sysctl_size = sizeof(sysctl_rslt);
98
99         if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0)
100                 return "No battery";
101
102         present_rate = sysctl_rslt;
103         if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0)
104                 return "No battery";
105
106         remaining = sysctl_rslt;
107         if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL,0) != 0)
108                 return "No battery";
109
110         state = sysctl_rslt;
111         if (state == 0 && present_rate == 100)
112                 status = CS_FULL;
113         else if (state == 0 && present_rate < 100)
114                 status = CS_CHARGING;
115         else
116                 status = CS_DISCHARGING;
117
118         full_design = sysctl_rslt;
119
120         if (state == 1) {
121                 int hours, minutes;
122                 minutes = remaining;
123                 hours = minutes / 60;
124                 minutes -= (hours * 60);
125                 (void)snprintf(part, sizeof(part), "%s %02d%% %02dh%02d",
126                                (status == CS_CHARGING ? "CHR" :
127                                 (status == CS_DISCHARGING ? "BAT" : "FULL")),
128                                present_rate,
129                                max(hours, 0), max(minutes, 0));
130         } else {
131                 (void)snprintf(part, sizeof(part), "%s %02d%%",
132                                (status == CS_CHARGING ? "CHR" :
133                                 (status == CS_DISCHARGING ? "BAT" : "FULL")),
134                                present_rate);
135         }
136 #endif
137         return part;
138 }