Xinqi Bao's Git

Set {r,t}xbytes 0 before incrementing them on OBSD
[slstatus.git] / components / battery.c
1 /* See LICENSE file for copyright and license details. */
2 #include <errno.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "../util.h"
7
8 static struct {
9 char *state;
10 char *symbol;
11 } map[] = {
12 { "Charging", "+" },
13 { "Discharging", "-" },
14 };
15
16 #if defined(__linux__)
17 #include <limits.h>
18
19 const char *
20 battery_perc(const char *bat)
21 {
22 int perc;
23 char path[PATH_MAX];
24
25 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/",
26 bat, "/capacity");
27 return (pscanf(path, "%d", &perc) == 1) ? bprintf("%d", perc) : NULL;
28 }
29
30 const char *
31 battery_state(const char *bat)
32 {
33 size_t i;
34 char path[PATH_MAX], state[12];
35
36 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/",
37 bat, "/status");
38 if (pscanf(path, "%12s", state) != 1) {
39 return NULL;
40 }
41
42 for (i = 0; i < LEN(map); i++) {
43 if (!strcmp(map[i].state, state)) {
44 break;
45 }
46 }
47 return (i == LEN(map)) ? "?" : map[i].symbol;
48 }
49
50 const char *
51 battery_remaining(const char *bat)
52 {
53 int charge_now, current_now, m, h;
54 float timeleft;
55 char path[PATH_MAX], state[12];
56
57 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/",
58 bat, "/status");
59 if (pscanf(path, "%12s", state) != 1) {
60 return NULL;
61 }
62
63 if (!strcmp(state, "Discharging")) {
64 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/",
65 bat, "/charge_now");
66 if (pscanf(path, "%d", &charge_now) != 1) {
67 return NULL;
68 }
69 snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/",
70 bat, "/current_now");
71 if (pscanf(path, "%d", &current_now) != 1) {
72 return NULL;
73 }
74
75 timeleft = (float)charge_now / (float)current_now;
76 h = timeleft;
77 m = (timeleft - (float)h) * 60;
78
79 return bprintf("%dh %dm", h, m);
80 }
81
82 return "";
83 }
84 #elif defined(__OpenBSD__)
85 #include <fcntl.h>
86 #include <machine/apmvar.h>
87 #include <sys/ioctl.h>
88 #include <unistd.h>
89
90 static int
91 load_apm_power_info(struct apm_power_info *apm_info)
92 {
93 int fd;
94
95 fd = open("/dev/apm", O_RDONLY);
96 if (fd < 0) {
97 warn("open '/dev/apm':");
98 return 0;
99 }
100
101 memset(apm_info, 0, sizeof(struct apm_power_info));
102 if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) {
103 warn("ioctl 'APM_IOC_GETPOWER':");
104 close(fd);
105 return 0;
106 }
107 return close(fd), 1;
108 }
109
110 const char *
111 battery_perc(const char *unused)
112 {
113 struct apm_power_info apm_info;
114
115 if (load_apm_power_info(&apm_info)) {
116 return bprintf("%d", apm_info.battery_life);
117 }
118
119 return NULL;
120 }
121
122 const char *
123 battery_state(const char *unused)
124 {
125 struct apm_power_info apm_info;
126 size_t i;
127
128 if (load_apm_power_info(&apm_info)) {
129 for (i = 0; i < LEN(map); i++) {
130 if (map[i].state == apm_info.ac_state) {
131 break;
132 }
133 }
134 return (i == LEN(map)) ? "?" : map[i].symbol;
135 }
136
137 return NULL;
138 }
139
140 const char *
141 battery_remaining(const char *unused)
142 {
143 struct apm_power_info apm_info;
144
145 if (load_apm_power_info(&apm_info)) {
146 if (apm_info.ac_state != APM_AC_ON) {
147 return bprintf("%uh %02um", apm_info.minutes_left / 60,
148 apm_info.minutes_left % 60);
149 } else {
150 return "";
151 }
152 }
153
154 return NULL;
155 }
156 #endif