comparison src/power/linux/SDL_syspower.c @ 3205:f9a4aa1e1b34

Linux /proc/acpi: check for ac_adapter states, other cleanup. Still not tested, though!
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 30 Jun 2009 05:44:00 +0000
parents f77f50add24f
children f735edf338d3
comparison
equal deleted inserted replaced
3204:f77f50add24f 3205:f9a4aa1e1b34
32 #include <dirent.h> 32 #include <dirent.h>
33 #include <fcntl.h> 33 #include <fcntl.h>
34 34
35 #include "SDL_power.h" 35 #include "SDL_power.h"
36 36
37 static const char *proc_acpi_path = "/proc/acpi/battery"; 37 static const char *proc_acpi_battery_path = "/proc/acpi/battery";
38 38 static const char *proc_acpi_ac_adapter_path = "/proc/acpi/ac_adapter";
39 static int open_acpi_file(const char *node, const char *key) 39
40 { 40 static int open_acpi_file(const char *base, const char *node, const char *key)
41 const size_t pathlen = strlen(proc_acpi_path)+strlen(node)+strlen(key)+3; 41 {
42 const size_t pathlen = strlen(base) + strlen(node) + strlen(key) + 3;
42 char *path = (char *) alloca(pathlen); 43 char *path = (char *) alloca(pathlen);
43 if (path == NULL) { 44 if (path == NULL) {
44 return -1; /* oh well. */ 45 return -1; /* oh well. */
45 } 46 }
46 47
47 snprintf(path, pathlen, "%s/%s/%s", proc_acpi_path, node, key); 48 snprintf(path, pathlen, "%s/%s/%s", base, node, key);
48 return open(path, O_RDONLY); 49 return open(path, O_RDONLY);
49 } 50 }
50 51
51 52
52 static SDL_bool 53 static SDL_bool
53 load_acpi_file(const char *node, const char *key, char *buf, size_t buflen) 54 load_acpi_file(const char *base, const char *node, const char *key,
55 char *buf, size_t buflen)
54 { 56 {
55 ssize_t br = 0; 57 ssize_t br = 0;
56 const int fd = open_acpi_file(node, key); 58 const int fd = open_acpi_file(base, node, key);
57 if (fd == -1) { 59 if (fd == -1) {
58 return SDL_FALSE; 60 return SDL_FALSE;
59 } 61 }
60 br = read(fd, buf, buflen-1); 62 br = read(fd, buf, buflen-1);
61 close(fd); 63 close(fd);
64 } 66 }
65 buf[br] = '\0'; // null-terminate the string. 67 buf[br] = '\0'; // null-terminate the string.
66 return SDL_TRUE; 68 return SDL_TRUE;
67 } 69 }
68 70
71
69 static SDL_bool 72 static SDL_bool
70 make_acpi_key_val(char **_ptr, char **_key, char **_val) 73 make_proc_acpi_key_val(char **_ptr, char **_key, char **_val)
71 { 74 {
72 char *ptr = *_ptr; 75 char *ptr = *_ptr;
73 76
74 while (*ptr == ' ') { 77 while (*ptr == ' ') {
75 ptr++; /* skip whitespace. */ 78 ptr++; /* skip whitespace. */
112 *_ptr = ptr; /* store for next time. */ 115 *_ptr = ptr; /* store for next time. */
113 return SDL_TRUE; 116 return SDL_TRUE;
114 } 117 }
115 118
116 static void 119 static void
117 check_acpi(const char * fname, SDL_bool * have_ac, SDL_bool * have_battery, 120 check_proc_acpi_battery(const char * node, SDL_bool * have_battery,
118 SDL_bool * charging, int *seconds, int *percent) 121 SDL_bool * charging, int *seconds, int *percent)
119 { 122 {
120 int fd = -1; 123 const char *base = proc_acpi_battery_path;
121 char info[1024]; 124 char info[1024];
122 char state[1024]; 125 char state[1024];
123 ssize_t br = 0;
124 char *ptr = NULL; 126 char *ptr = NULL;
125 char *key = NULL; 127 char *key = NULL;
126 char *val = NULL; 128 char *val = NULL;
127 SDL_bool charge = SDL_FALSE; 129 SDL_bool charge = SDL_FALSE;
128 SDL_bool choose = SDL_FALSE; 130 SDL_bool choose = SDL_FALSE;
130 int maximum = -1; 132 int maximum = -1;
131 int remaining = -1; 133 int remaining = -1;
132 int secs = -1; 134 int secs = -1;
133 int pct = -1; 135 int pct = -1;
134 136
135 if (!load_acpi_file(fname, "state", state, sizeof (state))) { 137 if (!load_acpi_file(base, node, "state", state, sizeof (state))) {
136 return; 138 return;
137 } else if (!load_acpi_file(fname, "info", info, sizeof (info))) { 139 } else if (!load_acpi_file(base, node, "info", info, sizeof (info))) {
138 return; 140 return;
139 } 141 }
140 142
141 ptr = &state[0]; 143 ptr = &state[0];
142 while (make_acpi_key_val(&ptr, &key, &val)) { 144 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
143 if (strcmp(key, "present") == 0) { 145 if (strcmp(key, "present") == 0) {
144 if (strcmp(val, "yes") == 0) { 146 if (strcmp(val, "yes") == 0) {
145 *have_battery = SDL_TRUE; 147 *have_battery = SDL_TRUE;
146 } 148 }
147 } else if (strcmp(key, "charging state") == 0) { 149 } else if (strcmp(key, "charging state") == 0) {
148 /* !!! FIXME: what exactly _does_ charging/discharging mean? */ 150 /* !!! FIXME: what exactly _does_ charging/discharging mean? */
149 if (strcmp(val, "charging/discharging") == 0) { 151 if (strcmp(val, "charging/discharging") == 0) {
150 *have_ac = is_ac = SDL_TRUE;
151 charge = SDL_TRUE; 152 charge = SDL_TRUE;
152 } else if (strcmp(val, "charging") == 0) { 153 } else if (strcmp(val, "charging") == 0) {
153 *have_ac = is_ac = SDL_TRUE;
154 charge = SDL_TRUE;
155 } else if (strcmp(val, "charged") == 0) {
156 /* !!! FIXME: maybe another battery is discharging,
157 !!! FIXME: instead of AC connection. */
158 *have_ac = is_ac = SDL_TRUE;
159 charge = SDL_TRUE; 154 charge = SDL_TRUE;
160 } 155 }
161 } else if (strcmp(key, "remaining capacity") == 0) { 156 } else if (strcmp(key, "remaining capacity") == 0) {
162 char *endptr = NULL; 157 char *endptr = NULL;
163 const int cvt = (int) strtol(val, &endptr, 10); 158 const int cvt = (int) strtol(val, &endptr, 10);
164 if (*endptr == ' ') { 159 if (*endptr == ' ') {
165 remaining = cvt; 160 remaining = cvt;
166 } 161 }
167 } 162 }
168 } 163 }
169 164
170 ptr = &info[0]; 165 ptr = &info[0];
171 while (make_acpi_key_val(&ptr, &key, &val)) { 166 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
172 if (strcmp(key, "design capacity") == 0) { 167 if (strcmp(key, "design capacity") == 0) {
173 char *endptr = NULL; 168 char *endptr = NULL;
174 const int cvt = (int) strtol(val, &endptr, 10); 169 const int cvt = (int) strtol(val, &endptr, 10);
175 if (*endptr == ' ') { 170 if (*endptr == ' ') {
176 maximum = cvt; 171 maximum = cvt;
207 if (choose) { 202 if (choose) {
208 *seconds = secs; 203 *seconds = secs;
209 *percent = pct; 204 *percent = pct;
210 *charging = charge; 205 *charging = charge;
211 } 206 }
212 207 }
213 } 208
209 static void
210 check_proc_acpi_ac_adapter(const char * node, SDL_bool * have_ac)
211 {
212 const char *base = proc_acpi_ac_adapter_path;
213 char state[256];
214 char *ptr = NULL;
215 char *key = NULL;
216 char *val = NULL;
217 SDL_bool charge = SDL_FALSE;
218 SDL_bool choose = SDL_FALSE;
219 SDL_bool is_ac = SDL_FALSE;
220 int maximum = -1;
221 int remaining = -1;
222 int secs = -1;
223 int pct = -1;
224
225 if (!load_acpi_file(base, node, "state", state, sizeof (state))) {
226 return;
227 }
228
229 ptr = &state[0];
230 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
231 if (strcmp(key, "state") == 0) {
232 if (strcmp(val, "on-line") == 0) {
233 *have_ac = SDL_TRUE;
234 }
235 }
236 }
237 }
238
214 239
215 SDL_bool 240 SDL_bool
216 SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState * state, 241 SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState * state,
217 int *seconds, int *percent) 242 int *seconds, int *percent)
218 { 243 {
219 struct dirent *dent = NULL; 244 struct dirent *dent = NULL;
220 DIR *dirp = NULL; 245 DIR *dirp = NULL;
246 SDL_bool have_battery = SDL_FALSE;
221 SDL_bool have_ac = SDL_FALSE; 247 SDL_bool have_ac = SDL_FALSE;
222 SDL_bool have_battery = SDL_FALSE;
223 SDL_bool charging = SDL_FALSE; 248 SDL_bool charging = SDL_FALSE;
224 249
225 *seconds = -1; 250 *seconds = -1;
226 *percent = -1; 251 *percent = -1;
227 *state = SDL_POWERSTATE_UNKNOWN; 252 *state = SDL_POWERSTATE_UNKNOWN;
228 253
229 dirp = opendir(proc_acpi_path); 254 dirp = opendir(proc_acpi_battery_path);
230 if (dirp == NULL) { 255 if (dirp == NULL) {
231 return SDL_FALSE; /* can't use this interface. */ 256 return SDL_FALSE; /* can't use this interface. */
232 } 257 } else {
233 258 while ((dent = readdir(dirp)) != NULL) {
234 while ((dent = readdir(dirp)) != NULL) { 259 const char *node = dent->d_name;
235 const char *name = dent->d_name; 260 check_proc_acpi_battery(node, &have_battery, &charging,
236 check_acpi(name, &have_ac, &have_battery, &charging, seconds, percent); 261 seconds, percent);
262 }
263 closedir(dirp);
264 }
265
266 dirp = opendir(proc_acpi_ac_adapter_path);
267 if (dirp == NULL) {
268 return SDL_FALSE; /* can't use this interface. */
269 } else {
270 while ((dent = readdir(dirp)) != NULL) {
271 const char *node = dent->d_name;
272 check_proc_acpi_ac_adapter(node, &have_ac);
273 }
274 closedir(dirp);
237 } 275 }
238 276
239 if (!have_battery) { 277 if (!have_battery) {
240 *state = SDL_POWERSTATE_NO_BATTERY; 278 *state = SDL_POWERSTATE_NO_BATTERY;
241 } else if (charging) { 279 } else if (charging) {