Mercurial > sdl-ios-xcode
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) { |