21 #include "../../SDL_internal.h" 23 #ifndef SDL_POWER_DISABLED 29 #include <sys/types.h> 35 #include "../SDL_syspower.h" 37 #include "../../core/linux/SDL_dbus.h" 39 static const char *proc_apm_path =
"/proc/apm";
40 static const char *proc_acpi_battery_path =
"/proc/acpi/battery";
41 static const char *proc_acpi_ac_adapter_path =
"/proc/acpi/ac_adapter";
42 static const char *sys_class_power_supply_path =
"/sys/class/power_supply";
45 open_power_file(
const char *base,
const char *node,
const char *
key)
47 const size_t pathlen = strlen(base) + strlen(node) + strlen(key) + 3;
48 char *
path = (
char *) alloca(pathlen);
53 snprintf(path, pathlen,
"%s/%s/%s", base, node, key);
54 return open(path, O_RDONLY);
59 read_power_file(
const char *base,
const char *node,
const char *key,
60 char *
buf,
size_t buflen)
63 const int fd = open_power_file(base, node, key);
67 br = read(fd, buf, buflen-1);
78 make_proc_acpi_key_val(
char **_ptr,
char **_key,
char **_val)
92 while ((*ptr !=
':') && (*ptr !=
'\0')) {
102 while ((*ptr ==
' ') && (*ptr !=
'\0')) {
112 while ((*ptr !=
'\n') && (*ptr !=
'\0')) {
125 check_proc_acpi_battery(
const char * node,
SDL_bool * have_battery,
126 SDL_bool * charging,
int *seconds,
int *percent)
128 const char *base = proc_acpi_battery_path;
141 if (!read_power_file(base, node,
"state", state,
sizeof (state))) {
143 }
else if (!read_power_file(base, node,
"info", info,
sizeof (info))) {
148 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
149 if (strcmp(key,
"present") == 0) {
150 if (strcmp(val,
"yes") == 0) {
153 }
else if (strcmp(key,
"charging state") == 0) {
155 if (strcmp(val,
"charging/discharging") == 0) {
157 }
else if (strcmp(val,
"charging") == 0) {
160 }
else if (strcmp(key,
"remaining capacity") == 0) {
162 const int cvt = (int) strtol(val, &endptr, 10);
163 if (*endptr ==
' ') {
170 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
171 if (strcmp(key,
"design capacity") == 0) {
173 const int cvt = (int) strtol(val, &endptr, 10);
174 if (*endptr ==
' ') {
180 if ((maximum >= 0) && (remaining >= 0)) {
181 pct = (int) ((((
float) remaining) / ((
float) maximum)) * 100.0f);
184 }
else if (pct > 100) {
195 if ((secs < 0) && (*seconds < 0)) {
196 if ((pct < 0) && (*percent < 0)) {
199 if (pct > *percent) {
202 }
else if (secs > *seconds) {
214 check_proc_acpi_ac_adapter(
const char * node,
SDL_bool * have_ac)
216 const char *base = proc_acpi_ac_adapter_path;
222 if (!read_power_file(base, node,
"state", state,
sizeof (state))) {
227 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
228 if (strcmp(key,
"state") == 0) {
229 if (strcmp(val,
"on-line") == 0) {
239 int *seconds,
int *percent)
241 struct dirent *dent =
NULL;
251 dirp = opendir(proc_acpi_battery_path);
255 while ((dent = readdir(dirp)) !=
NULL) {
256 const char *node = dent->d_name;
257 check_proc_acpi_battery(node, &have_battery, &charging,
263 dirp = opendir(proc_acpi_ac_adapter_path);
267 while ((dent = readdir(dirp)) !=
NULL) {
268 const char *node = dent->d_name;
269 check_proc_acpi_ac_adapter(node, &have_ac);
276 }
else if (charging) {
278 }
else if (have_ac) {
289 next_string(
char **_ptr,
char **_str)
294 while (*ptr ==
' ') {
303 while ((*ptr !=
' ') && (*ptr !=
'\n') && (*ptr !=
'\0'))
315 int_string(
char *str,
int *val)
318 *val = (int) strtol(str, &endptr, 0);
319 return ((*str !=
'\0') && (*endptr ==
'\0'));
325 int *seconds,
int *percent)
329 int battery_status = 0;
330 int battery_flag = 0;
331 int battery_percent = 0;
332 int battery_time = 0;
333 const int fd = open(proc_apm_path, O_RDONLY);
343 br = read(fd, buf,
sizeof (buf) - 1);
351 if (!next_string(&ptr, &str)) {
354 if (!next_string(&ptr, &str)) {
357 if (!next_string(&ptr, &str)) {
361 if (!next_string(&ptr, &str)) {
363 }
else if (!int_string(str, &ac_status)) {
367 if (!next_string(&ptr, &str)) {
369 }
else if (!int_string(str, &battery_status)) {
372 if (!next_string(&ptr, &str)) {
374 }
else if (!int_string(str, &battery_flag)) {
377 if (!next_string(&ptr, &str)) {
380 if (str[strlen(str) - 1] ==
'%') {
381 str[strlen(str) - 1] =
'\0';
383 if (!int_string(str, &battery_percent)) {
387 if (!next_string(&ptr, &str)) {
389 }
else if (!int_string(str, &battery_time)) {
393 if (!next_string(&ptr, &str)) {
395 }
else if (strcmp(str,
"min") == 0) {
399 if (battery_flag == 0xFF) {
401 }
else if (battery_flag & (1 << 7)) {
403 }
else if (battery_flag & (1 << 3)) {
406 }
else if (ac_status == 1) {
417 const int pct = battery_percent;
418 const int secs = battery_time;
421 *percent = (pct > 100) ? 100 : pct;
434 const char *base = sys_class_power_supply_path;
438 dirp = opendir(base);
447 while ((dent = readdir(dirp)) !=
NULL) {
448 const char *
name = dent->d_name;
457 }
else if (!read_power_file(base, name,
"type", str,
sizeof (str))) {
459 }
else if (
SDL_strcmp(str,
"Battery\n") != 0) {
467 if (read_power_file(base, name,
"scope", str,
sizeof (str))) {
474 if (read_power_file(base, name,
"present", str,
sizeof (str)) && (
SDL_strcmp(str,
"0\n") == 0)) {
476 }
else if (!read_power_file(base, name,
"status", str,
sizeof (str))) {
478 }
else if (
SDL_strcmp(str,
"Charging\n") == 0) {
480 }
else if (
SDL_strcmp(str,
"Discharging\n") == 0) {
488 if (!read_power_file(base, name,
"capacity", str,
sizeof (str))) {
492 pct = (pct > 100) ? 100 : pct;
495 if (!read_power_file(base, name,
"time_to_empty_now", str,
sizeof (str))) {
499 secs = (secs <= 0) ? -1 : secs;
506 if ((secs < 0) && (*seconds < 0)) {
507 if ((pct < 0) && (*percent < 0)) {
509 }
else if (pct > *percent) {
512 }
else if (secs > *seconds) {
530 #define UPOWER_DBUS_NODE "org.freedesktop.UPower" 531 #define UPOWER_DBUS_PATH "/org/freedesktop/UPower" 532 #define UPOWER_DBUS_INTERFACE "org.freedesktop.UPower" 533 #define UPOWER_DEVICE_DBUS_INTERFACE "org.freedesktop.UPower.Device" 536 check_upower_device(DBusConnection *conn,
const char *path,
SDL_PowerState *state,
int *seconds,
int *percent)
546 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE,
"Type", DBUS_TYPE_UINT32, &ui32)) {
548 }
else if (ui32 != 2) {
550 }
else if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE,
"PowerSupply", DBUS_TYPE_BOOLEAN, &ui32)) {
554 }
else if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE,
"IsPresent", DBUS_TYPE_BOOLEAN, &ui32)) {
558 }
else if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE,
"State", DBUS_TYPE_UINT32, &ui32)) {
560 }
else if (ui32 == 1) {
562 }
else if ((ui32 == 2) || (ui32 == 3)) {
564 }
else if (ui32 == 4) {
570 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE,
"Percentage", DBUS_TYPE_DOUBLE, &d)) {
574 pct = (pct > 100) ? 100 : pct;
577 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE,
"TimeToEmpty", DBUS_TYPE_INT64, &si64)) {
581 secs = (secs <= 0) ? -1 : secs;
588 if ((secs < 0) && (*seconds < 0)) {
589 if ((pct < 0) && (*percent < 0)) {
591 }
else if (pct > *percent) {
594 }
else if (secs > *seconds) {
612 SDL_DBusContext *dbus = SDL_DBus_GetContext();
616 if (!SDL_DBus_CallMethodOnConnection(dbus->system_conn, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE,
"EnumerateDevices",
618 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &numpaths, DBUS_TYPE_INVALID)) {
627 for (i = 0; i < numpaths; i++) {
628 check_upower_device(dbus->system_conn, paths[i], state, seconds, percent);
632 dbus->free_string_array(paths);
SDL_bool SDL_GetPowerInfo_Linux_sys_class_power_supply(SDL_PowerState *, int *, int *)
SDL_bool SDL_GetPowerInfo_Linux_org_freedesktop_upower(SDL_PowerState *, int *, int *)
GLuint const GLchar * name
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
GLenum GLuint GLenum GLsizei const GLchar * buf
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
SDL_PowerState
The basic state for the system's power supply.
SDL_bool SDL_GetPowerInfo_Linux_proc_apm(SDL_PowerState *, int *, int *)
GLsizei const GLchar *const * path
GLsizei const GLuint * paths
SDL_bool SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState *, int *, int *)