summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/power
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/SDL-3.2.8/src/power')
-rw-r--r--contrib/SDL-3.2.8/src/power/SDL_power.c113
-rw-r--r--contrib/SDL-3.2.8/src/power/SDL_syspower.h46
-rw-r--r--contrib/SDL-3.2.8/src/power/android/SDL_syspower.c60
-rw-r--r--contrib/SDL-3.2.8/src/power/emscripten/SDL_syspower.c59
-rw-r--r--contrib/SDL-3.2.8/src/power/haiku/SDL_syspower.c123
-rw-r--r--contrib/SDL-3.2.8/src/power/linux/SDL_syspower.c648
-rw-r--r--contrib/SDL-3.2.8/src/power/macos/SDL_syspower.c185
-rw-r--r--contrib/SDL-3.2.8/src/power/n3ds/SDL_syspower.c104
-rw-r--r--contrib/SDL-3.2.8/src/power/psp/SDL_syspower.c61
-rw-r--r--contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.h28
-rw-r--r--contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.m105
-rw-r--r--contrib/SDL-3.2.8/src/power/vita/SDL_syspower.c61
-rw-r--r--contrib/SDL-3.2.8/src/power/windows/SDL_syspower.c70
13 files changed, 1663 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/power/SDL_power.c b/contrib/SDL-3.2.8/src/power/SDL_power.c
new file mode 100644
index 0000000..5dde3b1
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/SDL_power.c
@@ -0,0 +1,113 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22#include "SDL_syspower.h"
23
24/*
25 * Returns true if we have a definitive answer.
26 * false to try next implementation.
27 */
28typedef bool (*SDL_GetPowerInfo_Impl)(SDL_PowerState *state, int *seconds,
29 int *percent);
30
31#ifndef SDL_POWER_DISABLED
32#ifdef SDL_POWER_HARDWIRED
33// This is for things that _never_ have a battery
34static bool SDL_GetPowerInfo_Hardwired(SDL_PowerState *state, int *seconds, int *percent)
35{
36 *seconds = -1;
37 *percent = -1;
38 *state = SDL_POWERSTATE_NO_BATTERY;
39 return true;
40}
41#endif
42
43static SDL_GetPowerInfo_Impl implementations[] = {
44#ifdef SDL_POWER_LINUX // in order of preference. More than could work.
45 SDL_GetPowerInfo_Linux_org_freedesktop_upower,
46 SDL_GetPowerInfo_Linux_sys_class_power_supply,
47 SDL_GetPowerInfo_Linux_proc_acpi,
48 SDL_GetPowerInfo_Linux_proc_apm,
49#endif
50#ifdef SDL_POWER_WINDOWS // handles Win32, Win64, PocketPC.
51 SDL_GetPowerInfo_Windows,
52#endif
53#ifdef SDL_POWER_UIKIT // handles iPhone/iPad/etc
54 SDL_GetPowerInfo_UIKit,
55#endif
56#ifdef SDL_POWER_MACOSX // handles macOS, Darwin.
57 SDL_GetPowerInfo_MacOSX,
58#endif
59#ifdef SDL_POWER_HAIKU // with BeOS euc.jp apm driver. Does this work on Haiku?
60 SDL_GetPowerInfo_Haiku,
61#endif
62#ifdef SDL_POWER_ANDROID // handles Android.
63 SDL_GetPowerInfo_Android,
64#endif
65#ifdef SDL_POWER_PSP // handles PSP.
66 SDL_GetPowerInfo_PSP,
67#endif
68#ifdef SDL_POWER_VITA // handles PSVita.
69 SDL_GetPowerInfo_VITA,
70#endif
71#ifdef SDL_POWER_N3DS // handles N3DS.
72 SDL_GetPowerInfo_N3DS,
73#endif
74#ifdef SDL_POWER_EMSCRIPTEN // handles Emscripten
75 SDL_GetPowerInfo_Emscripten,
76#endif
77
78#ifdef SDL_POWER_HARDWIRED
79 SDL_GetPowerInfo_Hardwired,
80#endif
81};
82#endif
83
84SDL_PowerState SDL_GetPowerInfo(int *seconds, int *percent)
85{
86#ifndef SDL_POWER_DISABLED
87 const int total = sizeof(implementations) / sizeof(implementations[0]);
88 SDL_PowerState result = SDL_POWERSTATE_UNKNOWN;
89 int i;
90#endif
91
92 int _seconds, _percent;
93 // Make these never NULL for platform-specific implementations.
94 if (!seconds) {
95 seconds = &_seconds;
96 }
97 if (!percent) {
98 percent = &_percent;
99 }
100
101#ifndef SDL_POWER_DISABLED
102 for (i = 0; i < total; i++) {
103 if (implementations[i](&result, seconds, percent)) {
104 return result;
105 }
106 }
107#endif
108
109 // nothing was definitive.
110 *seconds = -1;
111 *percent = -1;
112 return SDL_POWERSTATE_UNKNOWN;
113}
diff --git a/contrib/SDL-3.2.8/src/power/SDL_syspower.h b/contrib/SDL-3.2.8/src/power/SDL_syspower.h
new file mode 100644
index 0000000..5f8fa53
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/SDL_syspower.h
@@ -0,0 +1,46 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// These are functions that need to be implemented by a port of SDL
24
25#ifndef SDL_syspower_h_
26#define SDL_syspower_h_
27
28// Not all of these are available in a given build. Use #ifdefs, etc.
29bool SDL_GetPowerInfo_Linux_org_freedesktop_upower(SDL_PowerState *, int *, int *);
30bool SDL_GetPowerInfo_Linux_sys_class_power_supply(SDL_PowerState *, int *, int *);
31bool SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState *, int *, int *);
32bool SDL_GetPowerInfo_Linux_proc_apm(SDL_PowerState *, int *, int *);
33bool SDL_GetPowerInfo_Windows(SDL_PowerState *, int *, int *);
34bool SDL_GetPowerInfo_UIKit(SDL_PowerState *, int *, int *);
35bool SDL_GetPowerInfo_MacOSX(SDL_PowerState *, int *, int *);
36bool SDL_GetPowerInfo_Haiku(SDL_PowerState *, int *, int *);
37bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *);
38bool SDL_GetPowerInfo_PSP(SDL_PowerState *, int *, int *);
39bool SDL_GetPowerInfo_VITA(SDL_PowerState *, int *, int *);
40bool SDL_GetPowerInfo_N3DS(SDL_PowerState *, int *, int *);
41bool SDL_GetPowerInfo_Emscripten(SDL_PowerState *, int *, int *);
42
43// this one is static in SDL_power.c
44/* bool SDL_GetPowerInfo_Hardwired(SDL_PowerState *, int *, int *);*/
45
46#endif // SDL_syspower_h_
diff --git a/contrib/SDL-3.2.8/src/power/android/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/android/SDL_syspower.c
new file mode 100644
index 0000000..7f8d3f9
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/android/SDL_syspower.c
@@ -0,0 +1,60 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_POWER_DISABLED
24#ifdef SDL_POWER_ANDROID
25
26#include "../SDL_syspower.h"
27
28#include "../../core/android/SDL_android.h"
29
30bool SDL_GetPowerInfo_Android(SDL_PowerState *state, int *seconds, int *percent)
31{
32 int battery;
33 int plugged;
34 int charged;
35
36 if (Android_JNI_GetPowerInfo(&plugged, &charged, &battery, seconds, percent) != -1) {
37 if (plugged) {
38 if (charged) {
39 *state = SDL_POWERSTATE_CHARGED;
40 } else if (battery) {
41 *state = SDL_POWERSTATE_CHARGING;
42 } else {
43 *state = SDL_POWERSTATE_NO_BATTERY;
44 *seconds = -1;
45 *percent = -1;
46 }
47 } else {
48 *state = SDL_POWERSTATE_ON_BATTERY;
49 }
50 } else {
51 *state = SDL_POWERSTATE_UNKNOWN;
52 *seconds = -1;
53 *percent = -1;
54 }
55
56 return true;
57}
58
59#endif // SDL_POWER_ANDROID
60#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/emscripten/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/emscripten/SDL_syspower.c
new file mode 100644
index 0000000..14928de
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/emscripten/SDL_syspower.c
@@ -0,0 +1,59 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_POWER_DISABLED
24#ifdef SDL_POWER_EMSCRIPTEN
25
26#include <emscripten/html5.h>
27
28bool SDL_GetPowerInfo_Emscripten(SDL_PowerState *state, int *seconds, int *percent)
29{
30 EmscriptenBatteryEvent batteryState;
31 int haveBattery = 0;
32
33 if (emscripten_get_battery_status(&batteryState) == EMSCRIPTEN_RESULT_NOT_SUPPORTED) {
34 return false;
35 }
36
37 haveBattery = batteryState.level != 1.0 || !batteryState.charging || batteryState.chargingTime != 0.0;
38
39 if (!haveBattery) {
40 *state = SDL_POWERSTATE_NO_BATTERY;
41 *seconds = -1;
42 *percent = -1;
43 return true;
44 }
45
46 if (batteryState.charging) {
47 *state = batteryState.chargingTime == 0.0 ? SDL_POWERSTATE_CHARGED : SDL_POWERSTATE_CHARGING;
48 } else {
49 *state = SDL_POWERSTATE_ON_BATTERY;
50 }
51
52 *seconds = (int)batteryState.dischargingTime;
53 *percent = (int)batteryState.level * 100;
54
55 return true;
56}
57
58#endif // SDL_POWER_EMSCRIPTEN
59#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/haiku/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/haiku/SDL_syspower.c
new file mode 100644
index 0000000..c334fa6
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/haiku/SDL_syspower.c
@@ -0,0 +1,123 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23// uses BeOS euc.jp apm driver.
24// !!! FIXME: does this thing even work on Haiku?
25
26#ifndef SDL_POWER_DISABLED
27#ifdef SDL_POWER_HAIKU
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <ctype.h>
34#include <drivers/Drivers.h>
35
36// These values are from apm.h ...
37#define APM_DEVICE_PATH "/dev/misc/apm"
38#define APM_FUNC_OFFSET 0x5300
39#define APM_FUNC_GET_POWER_STATUS 10
40#define APM_DEVICE_ALL 1
41#define APM_BIOS_CALL (B_DEVICE_OP_CODES_END + 3)
42
43bool SDL_GetPowerInfo_Haiku(SDL_PowerState *state, int *seconds, int *percent)
44{
45 const int fd = open("/dev/misc/apm", O_RDONLY | O_CLOEXEC);
46 bool need_details = false;
47 uint16 regs[6];
48 uint8 ac_status;
49 uint8 battery_status;
50 uint8 battery_flags;
51 uint8 battery_life;
52 uint32 battery_time;
53 int rc;
54
55 if (fd == -1) {
56 return false; // maybe some other method will work?
57 }
58
59 SDL_memset(regs, '\0', sizeof(regs));
60 regs[0] = APM_FUNC_OFFSET + APM_FUNC_GET_POWER_STATUS;
61 regs[1] = APM_DEVICE_ALL;
62 rc = ioctl(fd, APM_BIOS_CALL, regs);
63 close(fd);
64
65 if (rc < 0) {
66 return false;
67 }
68
69 ac_status = regs[1] >> 8;
70 battery_status = regs[1] & 0xFF;
71 battery_flags = regs[2] >> 8;
72 battery_life = regs[2] & 0xFF;
73 battery_time = (uint32)regs[3];
74
75 // in theory, _something_ should be set in battery_flags, right?
76 if (battery_flags == 0x00) { // older APM BIOS? Less fields.
77 battery_time = 0xFFFF;
78 if (battery_status == 0xFF) {
79 battery_flags = 0xFF;
80 } else {
81 battery_flags = (1 << battery_status);
82 }
83 }
84
85 if ((battery_time != 0xFFFF) && (battery_time & (1 << 15))) {
86 // time is in minutes, not seconds
87 battery_time = (battery_time & 0x7FFF) * 60;
88 }
89
90 if (battery_flags == 0xFF) { // unknown state
91 *state = SDL_POWERSTATE_UNKNOWN;
92 } else if (battery_flags & (1 << 7)) { // no battery
93 *state = SDL_POWERSTATE_NO_BATTERY;
94 } else if (battery_flags & (1 << 3)) { // charging
95 *state = SDL_POWERSTATE_CHARGING;
96 need_details = true;
97 } else if (ac_status == 1) {
98 *state = SDL_POWERSTATE_CHARGED; // on AC, not charging.
99 need_details = true;
100 } else {
101 *state = SDL_POWERSTATE_ON_BATTERY; // not on AC.
102 need_details = true;
103 }
104
105 *percent = -1;
106 *seconds = -1;
107 if (need_details) {
108 const int pct = (int)battery_life;
109 const int secs = (int)battery_time;
110
111 if (pct != 255) { // 255 == unknown
112 *percent = (pct > 100) ? 100 : pct; // clamp between 0%, 100%
113 }
114 if (secs != 0xFFFF) { // 0xFFFF == unknown
115 *seconds = secs;
116 }
117 }
118
119 return true; // the definitive answer if APM driver replied.
120}
121
122#endif // SDL_POWER_HAIKU
123#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/linux/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/linux/SDL_syspower.c
new file mode 100644
index 0000000..428be4a
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/linux/SDL_syspower.c
@@ -0,0 +1,648 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_POWER_DISABLED
24#ifdef SDL_POWER_LINUX
25
26#include <stdio.h>
27#include <unistd.h>
28
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <dirent.h>
32#include <fcntl.h>
33
34#include "../SDL_syspower.h"
35
36#include "../../core/linux/SDL_dbus.h"
37
38static const char *proc_apm_path = "/proc/apm";
39static const char *proc_acpi_battery_path = "/proc/acpi/battery";
40static const char *proc_acpi_ac_adapter_path = "/proc/acpi/ac_adapter";
41static const char *sys_class_power_supply_path = "/sys/class/power_supply";
42
43static int open_power_file(const char *base, const char *node, const char *key)
44{
45 int fd;
46 const size_t pathlen = SDL_strlen(base) + SDL_strlen(node) + SDL_strlen(key) + 3;
47 char *path = SDL_stack_alloc(char, pathlen);
48 if (!path) {
49 return -1; // oh well.
50 }
51
52 (void)SDL_snprintf(path, pathlen, "%s/%s/%s", base, node, key);
53 fd = open(path, O_RDONLY | O_CLOEXEC);
54 SDL_stack_free(path);
55 return fd;
56}
57
58static bool read_power_file(const char *base, const char *node, const char *key,
59 char *buf, size_t buflen)
60{
61 ssize_t br = 0;
62 const int fd = open_power_file(base, node, key);
63 if (fd == -1) {
64 return false;
65 }
66 br = read(fd, buf, buflen - 1);
67 close(fd);
68 if (br < 0) {
69 return false;
70 }
71 buf[br] = '\0'; // null-terminate the string.
72 return true;
73}
74
75static bool make_proc_acpi_key_val(char **_ptr, char **_key, char **_val)
76{
77 char *ptr = *_ptr;
78
79 while (*ptr == ' ') {
80 ptr++; // skip whitespace.
81 }
82
83 if (*ptr == '\0') {
84 return false; // EOF.
85 }
86
87 *_key = ptr;
88
89 while ((*ptr != ':') && (*ptr != '\0')) {
90 ptr++;
91 }
92
93 if (*ptr == '\0') {
94 return false; // (unexpected) EOF.
95 }
96
97 *(ptr++) = '\0'; // terminate the key.
98
99 while (*ptr == ' ') {
100 ptr++; // skip whitespace.
101 }
102
103 if (*ptr == '\0') {
104 return false; // (unexpected) EOF.
105 }
106
107 *_val = ptr;
108
109 while ((*ptr != '\n') && (*ptr != '\0')) {
110 ptr++;
111 }
112
113 if (*ptr != '\0') {
114 *(ptr++) = '\0'; // terminate the value.
115 }
116
117 *_ptr = ptr; // store for next time.
118 return true;
119}
120
121static void check_proc_acpi_battery(const char *node, bool *have_battery,
122 bool *charging, int *seconds, int *percent)
123{
124 const char *base = proc_acpi_battery_path;
125 char info[1024];
126 char state[1024];
127 char *ptr = NULL;
128 char *key = NULL;
129 char *val = NULL;
130 bool charge = false;
131 bool choose = false;
132 int maximum = -1;
133 int remaining = -1;
134 int secs = -1;
135 int pct = -1;
136
137 if (!read_power_file(base, node, "state", state, sizeof(state))) {
138 return;
139 } else if (!read_power_file(base, node, "info", info, sizeof(info))) {
140 return;
141 }
142
143 ptr = &state[0];
144 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
145 if (SDL_strcasecmp(key, "present") == 0) {
146 if (SDL_strcasecmp(val, "yes") == 0) {
147 *have_battery = true;
148 }
149 } else if (SDL_strcasecmp(key, "charging state") == 0) {
150 // !!! FIXME: what exactly _does_ charging/discharging mean?
151 if (SDL_strcasecmp(val, "charging/discharging") == 0) {
152 charge = true;
153 } else if (SDL_strcasecmp(val, "charging") == 0) {
154 charge = true;
155 }
156 } else if (SDL_strcasecmp(key, "remaining capacity") == 0) {
157 char *endptr = NULL;
158 const int cvt = (int)SDL_strtol(val, &endptr, 10);
159 if (*endptr == ' ') {
160 remaining = cvt;
161 }
162 }
163 }
164
165 ptr = &info[0];
166 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
167 if (SDL_strcasecmp(key, "design capacity") == 0) {
168 char *endptr = NULL;
169 const int cvt = (int)SDL_strtol(val, &endptr, 10);
170 if (*endptr == ' ') {
171 maximum = cvt;
172 }
173 }
174 }
175
176 if ((maximum >= 0) && (remaining >= 0)) {
177 pct = (int)((((float)remaining) / ((float)maximum)) * 100.0f);
178 if (pct < 0) {
179 pct = 0;
180 } else if (pct > 100) {
181 pct = 100;
182 }
183 }
184
185 // !!! FIXME: calculate (secs).
186
187 /*
188 * We pick the battery that claims to have the most minutes left.
189 * (failing a report of minutes, we'll take the highest percent.)
190 */
191 if ((secs < 0) && (*seconds < 0)) {
192 if ((pct < 0) && (*percent < 0)) {
193 choose = true; // at least we know there's a battery.
194 }
195 if (pct > *percent) {
196 choose = true;
197 }
198 } else if (secs > *seconds) {
199 choose = true;
200 }
201
202 if (choose) {
203 *seconds = secs;
204 *percent = pct;
205 *charging = charge;
206 }
207}
208
209static void check_proc_acpi_ac_adapter(const char *node, bool *have_ac)
210{
211 const char *base = proc_acpi_ac_adapter_path;
212 char state[256];
213 char *ptr = NULL;
214 char *key = NULL;
215 char *val = NULL;
216
217 if (!read_power_file(base, node, "state", state, sizeof(state))) {
218 return;
219 }
220
221 ptr = &state[0];
222 while (make_proc_acpi_key_val(&ptr, &key, &val)) {
223 if (SDL_strcasecmp(key, "state") == 0) {
224 if (SDL_strcasecmp(val, "on-line") == 0) {
225 *have_ac = true;
226 }
227 }
228 }
229}
230
231bool SDL_GetPowerInfo_Linux_proc_acpi(SDL_PowerState *state, int *seconds, int *percent)
232{
233 struct dirent *dent = NULL;
234 DIR *dirp = NULL;
235 bool have_battery = false;
236 bool have_ac = false;
237 bool charging = false;
238
239 *seconds = -1;
240 *percent = -1;
241 *state = SDL_POWERSTATE_UNKNOWN;
242
243 dirp = opendir(proc_acpi_battery_path);
244 if (!dirp) {
245 return false; // can't use this interface.
246 } else {
247 while ((dent = readdir(dirp)) != NULL) {
248 const char *node = dent->d_name;
249 check_proc_acpi_battery(node, &have_battery, &charging,
250 seconds, percent);
251 }
252 closedir(dirp);
253 }
254
255 dirp = opendir(proc_acpi_ac_adapter_path);
256 if (!dirp) {
257 return false; // can't use this interface.
258 } else {
259 while ((dent = readdir(dirp)) != NULL) {
260 const char *node = dent->d_name;
261 check_proc_acpi_ac_adapter(node, &have_ac);
262 }
263 closedir(dirp);
264 }
265
266 if (!have_battery) {
267 *state = SDL_POWERSTATE_NO_BATTERY;
268 } else if (charging) {
269 *state = SDL_POWERSTATE_CHARGING;
270 } else if (have_ac) {
271 *state = SDL_POWERSTATE_CHARGED;
272 } else {
273 *state = SDL_POWERSTATE_ON_BATTERY;
274 }
275
276 return true; // definitive answer.
277}
278
279static bool next_string(char **_ptr, char **_str)
280{
281 char *ptr = *_ptr;
282 char *str;
283
284 while (*ptr == ' ') { // skip any spaces...
285 ptr++;
286 }
287
288 if (*ptr == '\0') {
289 return false;
290 }
291
292 str = ptr;
293 while ((*ptr != ' ') && (*ptr != '\n') && (*ptr != '\0')) {
294 ptr++;
295 }
296
297 if (*ptr != '\0') {
298 *(ptr++) = '\0';
299 }
300
301 *_str = str;
302 *_ptr = ptr;
303 return true;
304}
305
306static bool int_string(char *str, int *val)
307{
308 char *endptr = NULL;
309 *val = (int)SDL_strtol(str, &endptr, 0);
310 return (*str != '\0') && (*endptr == '\0');
311}
312
313// http://lxr.linux.no/linux+v2.6.29/drivers/char/apm-emulation.c
314bool SDL_GetPowerInfo_Linux_proc_apm(SDL_PowerState *state, int *seconds, int *percent)
315{
316 bool need_details = false;
317 int ac_status = 0;
318 int battery_status = 0;
319 int battery_flag = 0;
320 int battery_percent = 0;
321 int battery_time = 0;
322 const int fd = open(proc_apm_path, O_RDONLY | O_CLOEXEC);
323 char buf[128];
324 char *ptr = &buf[0];
325 char *str = NULL;
326 ssize_t br;
327
328 if (fd == -1) {
329 return false; // can't use this interface.
330 }
331
332 br = read(fd, buf, sizeof(buf) - 1);
333 close(fd);
334
335 if (br < 0) {
336 return false;
337 }
338
339 buf[br] = '\0'; // null-terminate the string.
340 if (!next_string(&ptr, &str)) { // driver version
341 return false;
342 }
343 if (!next_string(&ptr, &str)) { // BIOS version
344 return false;
345 }
346 if (!next_string(&ptr, &str)) { // APM flags
347 return false;
348 }
349
350 if (!next_string(&ptr, &str)) { // AC line status
351 return false;
352 } else if (!int_string(str, &ac_status)) {
353 return false;
354 }
355
356 if (!next_string(&ptr, &str)) { // battery status
357 return false;
358 } else if (!int_string(str, &battery_status)) {
359 return false;
360 }
361 if (!next_string(&ptr, &str)) { // battery flag
362 return false;
363 } else if (!int_string(str, &battery_flag)) {
364 return false;
365 }
366 if (!next_string(&ptr, &str)) { // remaining battery life percent
367 return false;
368 }
369 if (str[SDL_strlen(str) - 1] == '%') {
370 str[SDL_strlen(str) - 1] = '\0';
371 }
372 if (!int_string(str, &battery_percent)) {
373 return false;
374 }
375
376 if (!next_string(&ptr, &str)) { // remaining battery life time
377 return false;
378 } else if (!int_string(str, &battery_time)) {
379 return false;
380 }
381
382 if (!next_string(&ptr, &str)) { // remaining battery life time units
383 return false;
384 } else if (SDL_strcasecmp(str, "min") == 0) {
385 battery_time *= 60;
386 }
387
388 if (battery_flag == 0xFF) { // unknown state
389 *state = SDL_POWERSTATE_UNKNOWN;
390 } else if (battery_flag & (1 << 7)) { // no battery
391 *state = SDL_POWERSTATE_NO_BATTERY;
392 } else if (battery_flag & (1 << 3)) { // charging
393 *state = SDL_POWERSTATE_CHARGING;
394 need_details = true;
395 } else if (ac_status == 1) {
396 *state = SDL_POWERSTATE_CHARGED; // on AC, not charging.
397 need_details = true;
398 } else {
399 *state = SDL_POWERSTATE_ON_BATTERY;
400 need_details = true;
401 }
402
403 *percent = -1;
404 *seconds = -1;
405 if (need_details) {
406 const int pct = battery_percent;
407 const int secs = battery_time;
408
409 if (pct >= 0) { // -1 == unknown
410 *percent = (pct > 100) ? 100 : pct; // clamp between 0%, 100%
411 }
412 if (secs >= 0) { // -1 == unknown
413 *seconds = secs;
414 }
415 }
416
417 return true;
418}
419
420bool SDL_GetPowerInfo_Linux_sys_class_power_supply(SDL_PowerState *state, int *seconds, int *percent)
421{
422 const char *base = sys_class_power_supply_path;
423 struct dirent *dent;
424 DIR *dirp;
425
426 dirp = opendir(base);
427 if (!dirp) {
428 return false;
429 }
430
431 *state = SDL_POWERSTATE_NO_BATTERY; // assume we're just plugged in.
432 *seconds = -1;
433 *percent = -1;
434
435 while ((dent = readdir(dirp)) != NULL) {
436 const char *name = dent->d_name;
437 bool choose = false;
438 char str[64];
439 SDL_PowerState st;
440 int secs;
441 int pct;
442 int energy;
443 int power;
444
445 if ((SDL_strcmp(name, ".") == 0) || (SDL_strcmp(name, "..") == 0)) {
446 continue; // skip these, of course.
447 } else if (!read_power_file(base, name, "type", str, sizeof(str))) {
448 continue; // Don't know _what_ we're looking at. Give up on it.
449 } else if (SDL_strcasecmp(str, "Battery\n") != 0) {
450 continue; // we don't care about UPS and such.
451 }
452
453 /* if the scope is "device," it might be something like a PS4
454 controller reporting its own battery, and not something that powers
455 the system. Most system batteries don't list a scope at all; we
456 assume it's a system battery if not specified. */
457 if (read_power_file(base, name, "scope", str, sizeof(str))) {
458 if (SDL_strcasecmp(str, "Device\n") == 0) {
459 continue; // skip external devices with their own batteries.
460 }
461 }
462
463 // some drivers don't offer this, so if it's not explicitly reported assume it's present.
464 if (read_power_file(base, name, "present", str, sizeof(str)) && (SDL_strcmp(str, "0\n") == 0)) {
465 st = SDL_POWERSTATE_NO_BATTERY;
466 } else if (!read_power_file(base, name, "status", str, sizeof(str))) {
467 st = SDL_POWERSTATE_UNKNOWN; // uh oh
468 } else if (SDL_strcasecmp(str, "Charging\n") == 0) {
469 st = SDL_POWERSTATE_CHARGING;
470 } else if (SDL_strcasecmp(str, "Discharging\n") == 0) {
471 st = SDL_POWERSTATE_ON_BATTERY;
472 } else if ((SDL_strcasecmp(str, "Full\n") == 0) || (SDL_strcasecmp(str, "Not charging\n") == 0)) {
473 st = SDL_POWERSTATE_CHARGED;
474 } else {
475 st = SDL_POWERSTATE_UNKNOWN; // uh oh
476 }
477
478 if (!read_power_file(base, name, "capacity", str, sizeof(str))) {
479 pct = -1;
480 } else {
481 pct = SDL_atoi(str);
482 pct = (pct > 100) ? 100 : pct; // clamp between 0%, 100%
483 }
484
485 if (read_power_file(base, name, "time_to_empty_now", str, sizeof(str))) {
486 secs = SDL_atoi(str);
487 secs = (secs <= 0) ? -1 : secs; // 0 == unknown
488 } else if (st == SDL_POWERSTATE_ON_BATTERY) {
489 /* energy is Watt*hours and power is Watts */
490 energy = (read_power_file(base, name, "energy_now", str, sizeof(str))) ? SDL_atoi(str) : -1;
491 power = (read_power_file(base, name, "power_now", str, sizeof(str))) ? SDL_atoi(str) : -1;
492 secs = (energy >= 0 && power > 0) ? (3600LL * energy) / power : -1;
493 } else {
494 secs = -1;
495 }
496
497 /*
498 * We pick the battery that claims to have the most minutes left.
499 * (failing a report of minutes, we'll take the highest percent.)
500 */
501 if ((secs < 0) && (*seconds < 0)) {
502 if ((pct < 0) && (*percent < 0)) {
503 choose = true; // at least we know there's a battery.
504 } else if (pct > *percent) {
505 choose = true;
506 }
507 } else if (secs > *seconds) {
508 choose = true;
509 }
510
511 if (choose) {
512 *seconds = secs;
513 *percent = pct;
514 *state = st;
515 }
516 }
517
518 closedir(dirp);
519 return true; // don't look any further.
520}
521
522// d-bus queries to org.freedesktop.UPower.
523#ifdef SDL_USE_LIBDBUS
524#define UPOWER_DBUS_NODE "org.freedesktop.UPower"
525#define UPOWER_DBUS_PATH "/org/freedesktop/UPower"
526#define UPOWER_DBUS_INTERFACE "org.freedesktop.UPower"
527#define UPOWER_DEVICE_DBUS_INTERFACE "org.freedesktop.UPower.Device"
528
529static void check_upower_device(DBusConnection *conn, const char *path, SDL_PowerState *state, int *seconds, int *percent)
530{
531 bool choose = false;
532 SDL_PowerState st;
533 int secs;
534 int pct;
535 Uint32 ui32 = 0;
536 Sint64 si64 = 0;
537 double d = 0.0;
538
539 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Type", DBUS_TYPE_UINT32, &ui32)) {
540 return; // Don't know _what_ we're looking at. Give up on it.
541 } else if (ui32 != 2) { // 2==Battery
542 return; // we don't care about UPS and such.
543 } else if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "PowerSupply", DBUS_TYPE_BOOLEAN, &ui32)) {
544 return;
545 } else if (!ui32) {
546 return; // we don't care about random devices with batteries, like wireless controllers, etc
547 }
548
549 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "IsPresent", DBUS_TYPE_BOOLEAN, &ui32)) {
550 return;
551 }
552 if (!ui32) {
553 st = SDL_POWERSTATE_NO_BATTERY;
554 } else {
555 /* Get updated information on the battery status
556 * This can occasionally fail, and we'll just return slightly stale data in that case
557 */
558 SDL_DBus_CallMethodOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Refresh", DBUS_TYPE_INVALID, DBUS_TYPE_INVALID);
559
560 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "State", DBUS_TYPE_UINT32, &ui32)) {
561 st = SDL_POWERSTATE_UNKNOWN; // uh oh
562 } else if (ui32 == 1) { // 1 == charging
563 st = SDL_POWERSTATE_CHARGING;
564 } else if ((ui32 == 2) || (ui32 == 3) || (ui32 == 6)) {
565 /* 2 == discharging;
566 * 3 == empty;
567 * 6 == "pending discharge" which GNOME interprets as equivalent
568 * to discharging */
569 st = SDL_POWERSTATE_ON_BATTERY;
570 } else if ((ui32 == 4) || (ui32 == 5)) {
571 /* 4 == full;
572 * 5 == "pending charge" which GNOME shows as "Not charging",
573 * used when a battery is configured to stop charging at a
574 * lower than 100% threshold */
575 st = SDL_POWERSTATE_CHARGED;
576 } else {
577 st = SDL_POWERSTATE_UNKNOWN; // uh oh
578 }
579 }
580
581 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Percentage", DBUS_TYPE_DOUBLE, &d)) {
582 pct = -1; // some old/cheap batteries don't set this property.
583 } else {
584 pct = (int)d;
585 pct = (pct > 100) ? 100 : pct; // clamp between 0%, 100%
586 }
587
588 if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "TimeToEmpty", DBUS_TYPE_INT64, &si64)) {
589 secs = -1;
590 } else {
591 secs = (int)si64;
592 secs = (secs <= 0) ? -1 : secs; // 0 == unknown
593 }
594
595 /*
596 * We pick the battery that claims to have the most minutes left.
597 * (failing a report of minutes, we'll take the highest percent.)
598 */
599 if ((secs < 0) && (*seconds < 0)) {
600 if ((pct < 0) && (*percent < 0)) {
601 choose = true; // at least we know there's a battery.
602 } else if (pct > *percent) {
603 choose = true;
604 }
605 } else if (secs > *seconds) {
606 choose = true;
607 }
608
609 if (choose) {
610 *seconds = secs;
611 *percent = pct;
612 *state = st;
613 }
614}
615#endif
616
617bool SDL_GetPowerInfo_Linux_org_freedesktop_upower(SDL_PowerState *state, int *seconds, int *percent)
618{
619 bool result = false;
620
621#ifdef SDL_USE_LIBDBUS
622 SDL_DBusContext *dbus = SDL_DBus_GetContext();
623 char **paths = NULL;
624 int i, numpaths = 0;
625
626 if (!dbus || !SDL_DBus_CallMethodOnConnection(dbus->system_conn, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE, "EnumerateDevices",
627 DBUS_TYPE_INVALID,
628 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &numpaths, DBUS_TYPE_INVALID)) {
629 return false; // try a different approach than UPower.
630 }
631
632 result = true; // Clearly we can use this interface.
633 *state = SDL_POWERSTATE_NO_BATTERY; // assume we're just plugged in.
634 *seconds = -1;
635 *percent = -1;
636
637 for (i = 0; i < numpaths; i++) {
638 check_upower_device(dbus->system_conn, paths[i], state, seconds, percent);
639 }
640
641 dbus->free_string_array(paths);
642#endif // SDL_USE_LIBDBUS
643
644 return result;
645}
646
647#endif // SDL_POWER_LINUX
648#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/macos/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/macos/SDL_syspower.c
new file mode 100644
index 0000000..4764da9
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/macos/SDL_syspower.c
@@ -0,0 +1,185 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_POWER_DISABLED
24#ifdef SDL_POWER_MACOSX
25
26#include <CoreFoundation/CoreFoundation.h>
27#include <IOKit/ps/IOPowerSources.h>
28#include <IOKit/ps/IOPSKeys.h>
29
30// CoreFoundation is so verbose...
31#define STRMATCH(a, b) (CFStringCompare(a, b, 0) == kCFCompareEqualTo)
32#define GETVAL(k, v) \
33 CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **)v)
34
35// Note that AC power sources also include a laptop battery it is charging.
36static void checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery,
37 bool *charging, int *seconds, int *percent)
38{
39 CFStringRef strval; // don't CFRelease() this.
40 CFBooleanRef bval;
41 CFNumberRef numval;
42 bool charge = false;
43 bool choose = false;
44 bool is_ac = false;
45 int secs = -1;
46 int maxpct = -1;
47 int pct = -1;
48
49 if ((GETVAL(kIOPSIsPresentKey, &bval)) && (bval == kCFBooleanFalse)) {
50 return; // nothing to see here.
51 }
52
53 if (!GETVAL(kIOPSPowerSourceStateKey, &strval)) {
54 return;
55 }
56
57 if (STRMATCH(strval, CFSTR(kIOPSACPowerValue))) {
58 is_ac = *have_ac = true;
59 } else if (!STRMATCH(strval, CFSTR(kIOPSBatteryPowerValue))) {
60 return; // not a battery?
61 }
62
63 if ((GETVAL(kIOPSIsChargingKey, &bval)) && (bval == kCFBooleanTrue)) {
64 charge = true;
65 }
66
67 if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
68 SInt32 val = -1;
69 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
70 if (val > 0) {
71 *have_battery = true;
72 maxpct = (int)val;
73 }
74 }
75
76 if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
77 SInt32 val = -1;
78 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
79 if (val > 0) {
80 *have_battery = true;
81 maxpct = (int)val;
82 }
83 }
84
85 if (GETVAL(kIOPSTimeToEmptyKey, &numval)) {
86 SInt32 val = -1;
87 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
88
89 // macOS reports 0 minutes until empty if you're plugged in. :(
90 if ((val == 0) && (is_ac)) {
91 val = -1; // !!! FIXME: calc from timeToFull and capacity?
92 }
93
94 secs = (int)val;
95 if (secs > 0) {
96 secs *= 60; // value is in minutes, so convert to seconds.
97 }
98 }
99
100 if (GETVAL(kIOPSCurrentCapacityKey, &numval)) {
101 SInt32 val = -1;
102 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
103 pct = (int)val;
104 }
105
106 if ((pct > 0) && (maxpct > 0)) {
107 pct = (int)((((double)pct) / ((double)maxpct)) * 100.0);
108 }
109
110 if (pct > 100) {
111 pct = 100;
112 }
113
114 /*
115 * We pick the battery that claims to have the most minutes left.
116 * (failing a report of minutes, we'll take the highest percent.)
117 */
118 if ((secs < 0) && (*seconds < 0)) {
119 if ((pct < 0) && (*percent < 0)) {
120 choose = true; // at least we know there's a battery.
121 }
122 if (pct > *percent) {
123 choose = true;
124 }
125 } else if (secs > *seconds) {
126 choose = true;
127 }
128
129 if (choose) {
130 *seconds = secs;
131 *percent = pct;
132 *charging = charge;
133 }
134}
135
136#undef GETVAL
137#undef STRMATCH
138
139bool SDL_GetPowerInfo_MacOSX(SDL_PowerState *state, int *seconds, int *percent)
140{
141 CFTypeRef blob = IOPSCopyPowerSourcesInfo();
142
143 *seconds = -1;
144 *percent = -1;
145 *state = SDL_POWERSTATE_UNKNOWN;
146
147 if (blob != NULL) {
148 CFArrayRef list = IOPSCopyPowerSourcesList(blob);
149 if (list != NULL) {
150 // don't CFRelease() the list items, or dictionaries!
151 bool have_ac = false;
152 bool have_battery = false;
153 bool charging = false;
154 const CFIndex total = CFArrayGetCount(list);
155 CFIndex i;
156 for (i = 0; i < total; i++) {
157 CFTypeRef ps = (CFTypeRef)CFArrayGetValueAtIndex(list, i);
158 CFDictionaryRef dict =
159 IOPSGetPowerSourceDescription(blob, ps);
160 if (dict != NULL) {
161 checkps(dict, &have_ac, &have_battery, &charging,
162 seconds, percent);
163 }
164 }
165
166 if (!have_battery) {
167 *state = SDL_POWERSTATE_NO_BATTERY;
168 } else if (charging) {
169 *state = SDL_POWERSTATE_CHARGING;
170 } else if (have_ac) {
171 *state = SDL_POWERSTATE_CHARGED;
172 } else {
173 *state = SDL_POWERSTATE_ON_BATTERY;
174 }
175
176 CFRelease(list);
177 }
178 CFRelease(blob);
179 }
180
181 return true; // always the definitive answer on macOS.
182}
183
184#endif // SDL_POWER_MACOSX
185#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/n3ds/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/n3ds/SDL_syspower.c
new file mode 100644
index 0000000..822398a
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/n3ds/SDL_syspower.c
@@ -0,0 +1,104 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "SDL_internal.h"
23
24#if !defined(SDL_POWER_DISABLED) && defined(SDL_POWER_N3DS)
25
26#include <3ds.h>
27
28static SDL_PowerState GetPowerState(void);
29static bool ReadStateFromPTMU(bool *is_plugged, u8 *is_charging);
30static int GetBatteryPercentage(void);
31
32#define BATTERY_PERCENT_REG 0xB
33#define BATTERY_PERCENT_REG_SIZE 2
34
35bool SDL_GetPowerInfo_N3DS(SDL_PowerState *state, int *seconds, int *percent)
36{
37 *state = GetPowerState();
38 *percent = GetBatteryPercentage();
39 *seconds = -1; // libctru doesn't provide a way to estimate battery life
40
41 return true;
42}
43
44static SDL_PowerState GetPowerState(void)
45{
46 bool is_plugged;
47 u8 is_charging;
48
49 if (!ReadStateFromPTMU(&is_plugged, &is_charging)) {
50 return SDL_POWERSTATE_UNKNOWN;
51 }
52
53 if (is_charging) {
54 return SDL_POWERSTATE_CHARGING;
55 }
56
57 if (is_plugged) {
58 return SDL_POWERSTATE_CHARGED;
59 }
60
61 return SDL_POWERSTATE_ON_BATTERY;
62}
63
64static bool ReadStateFromPTMU(bool *is_plugged, u8 *is_charging)
65{
66 if (R_FAILED(ptmuInit())) {
67 return SDL_SetError("Failed to initialise PTMU service");
68 }
69
70 if (R_FAILED(PTMU_GetAdapterState(is_plugged))) {
71 ptmuExit();
72 return SDL_SetError("Failed to read adapter state");
73 }
74
75 if (R_FAILED(PTMU_GetBatteryChargeState(is_charging))) {
76 ptmuExit();
77 return SDL_SetError("Failed to read battery charge state");
78 }
79
80 ptmuExit();
81 return true;
82}
83
84static int GetBatteryPercentage(void)
85{
86 u8 data[BATTERY_PERCENT_REG_SIZE];
87
88 if (R_FAILED(mcuHwcInit())) {
89 SDL_SetError("Failed to initialise mcuHwc service");
90 return -1;
91 }
92
93 if (R_FAILED(MCUHWC_ReadRegister(BATTERY_PERCENT_REG, data, BATTERY_PERCENT_REG_SIZE))) {
94 mcuHwcExit();
95 SDL_SetError("Failed to read battery register");
96 return -1;
97 }
98
99 mcuHwcExit();
100
101 return (int)SDL_round(data[0] + data[1] / 256.0);
102}
103
104#endif // !SDL_POWER_DISABLED && SDL_POWER_N3DS
diff --git a/contrib/SDL-3.2.8/src/power/psp/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/psp/SDL_syspower.c
new file mode 100644
index 0000000..231411f
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/psp/SDL_syspower.c
@@ -0,0 +1,61 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "SDL_internal.h"
23
24#ifndef SDL_POWER_DISABLED
25#ifdef SDL_POWER_PSP
26
27#include <psppower.h>
28
29bool SDL_GetPowerInfo_PSP(SDL_PowerState *state, int *seconds, int *percent)
30{
31 int battery = scePowerIsBatteryExist();
32 int plugged = scePowerIsPowerOnline();
33 int charging = scePowerIsBatteryCharging();
34
35 *state = SDL_POWERSTATE_UNKNOWN;
36 *seconds = -1;
37 *percent = -1;
38
39 if (!battery) {
40 *state = SDL_POWERSTATE_NO_BATTERY;
41 *seconds = -1;
42 *percent = -1;
43 } else if (charging) {
44 *state = SDL_POWERSTATE_CHARGING;
45 *percent = scePowerGetBatteryLifePercent();
46 *seconds = scePowerGetBatteryLifeTime() * 60;
47 } else if (plugged) {
48 *state = SDL_POWERSTATE_CHARGED;
49 *percent = scePowerGetBatteryLifePercent();
50 *seconds = scePowerGetBatteryLifeTime() * 60;
51 } else {
52 *state = SDL_POWERSTATE_ON_BATTERY;
53 *percent = scePowerGetBatteryLifePercent();
54 *seconds = scePowerGetBatteryLifeTime() * 60;
55 }
56
57 return true; // always the definitive answer on PSP.
58}
59
60#endif // SDL_POWER_PSP
61#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.h b/contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.h
new file mode 100644
index 0000000..41fc43b
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.h
@@ -0,0 +1,28 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifdef SDL_POWER_UIKIT
24
25void SDL_UIKit_UpdateBatteryMonitoring(void);
26bool SDL_GetPowerInfo_UIKit(SDL_PowerState *state, int *seconds, int *percent);
27
28#endif // SDL_POWER_UIKIT
diff --git a/contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.m b/contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.m
new file mode 100644
index 0000000..561f2de
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/uikit/SDL_syspower.m
@@ -0,0 +1,105 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_POWER_DISABLED
24#ifdef SDL_POWER_UIKIT
25
26#import <UIKit/UIKit.h>
27
28#include "SDL_syspower.h"
29
30#ifndef SDL_PLATFORM_TVOS
31// turn off the battery monitor if it's been more than X ms since last check.
32static const int BATTERY_MONITORING_TIMEOUT = 3000;
33static Uint64 SDL_UIKitLastPowerInfoQuery = 0;
34
35void SDL_UIKit_UpdateBatteryMonitoring(void)
36{
37 if (SDL_UIKitLastPowerInfoQuery) {
38 if (SDL_GetTicks() >= (SDL_UIKitLastPowerInfoQuery + BATTERY_MONITORING_TIMEOUT)) {
39 UIDevice *uidev = [UIDevice currentDevice];
40 SDL_assert([uidev isBatteryMonitoringEnabled] == YES);
41 [uidev setBatteryMonitoringEnabled:NO];
42 SDL_UIKitLastPowerInfoQuery = 0;
43 }
44 }
45}
46#else
47void SDL_UIKit_UpdateBatteryMonitoring(void)
48{
49 // Do nothing.
50}
51#endif // !SDL_PLATFORM_TVOS
52
53bool SDL_GetPowerInfo_UIKit(SDL_PowerState *state, int *seconds, int *percent)
54{
55#ifdef SDL_PLATFORM_TVOS
56 *state = SDL_POWERSTATE_NO_BATTERY;
57 *seconds = -1;
58 *percent = -1;
59#else // SDL_PLATFORM_TVOS
60 @autoreleasepool {
61 UIDevice *uidev = [UIDevice currentDevice];
62
63 if (!SDL_UIKitLastPowerInfoQuery) {
64 SDL_assert(uidev.isBatteryMonitoringEnabled == NO);
65 uidev.batteryMonitoringEnabled = YES;
66 }
67
68 /* UIKit_GL_SwapWindow() (etc) will check this and disable the battery
69 * monitoring if the app hasn't queried it in the last X seconds.
70 * Apparently monitoring the battery burns battery life. :)
71 * Apple's docs say not to monitor the battery unless you need it.
72 */
73 SDL_UIKitLastPowerInfoQuery = SDL_GetTicks();
74
75 *seconds = -1; // no API to estimate this in UIKit.
76
77 switch (uidev.batteryState) {
78 case UIDeviceBatteryStateCharging:
79 *state = SDL_POWERSTATE_CHARGING;
80 break;
81
82 case UIDeviceBatteryStateFull:
83 *state = SDL_POWERSTATE_CHARGED;
84 break;
85
86 case UIDeviceBatteryStateUnplugged:
87 *state = SDL_POWERSTATE_ON_BATTERY;
88 break;
89
90 case UIDeviceBatteryStateUnknown:
91 default:
92 *state = SDL_POWERSTATE_UNKNOWN;
93 break;
94 }
95
96 const float level = uidev.batteryLevel;
97 *percent = ((level < 0.0f) ? -1 : ((int)((level * 100) + 0.5f)));
98 }
99#endif // SDL_PLATFORM_TVOS
100
101 return true; // always the definitive answer on iOS.
102}
103
104#endif // SDL_POWER_UIKIT
105#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/vita/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/vita/SDL_syspower.c
new file mode 100644
index 0000000..5dc8f5e
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/vita/SDL_syspower.c
@@ -0,0 +1,61 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "SDL_internal.h"
23
24#ifndef SDL_POWER_DISABLED
25#ifdef SDL_POWER_VITA
26
27#include <psp2/power.h>
28
29bool SDL_GetPowerInfo_VITA(SDL_PowerState *state, int *seconds, int *percent)
30{
31 int battery = 1;
32 int plugged = scePowerIsPowerOnline();
33 int charging = scePowerIsBatteryCharging();
34
35 *state = SDL_POWERSTATE_UNKNOWN;
36 *seconds = -1;
37 *percent = -1;
38
39 if (!battery) {
40 *state = SDL_POWERSTATE_NO_BATTERY;
41 *seconds = -1;
42 *percent = -1;
43 } else if (charging) {
44 *state = SDL_POWERSTATE_CHARGING;
45 *percent = scePowerGetBatteryLifePercent();
46 *seconds = scePowerGetBatteryLifeTime() * 60;
47 } else if (plugged) {
48 *state = SDL_POWERSTATE_CHARGED;
49 *percent = scePowerGetBatteryLifePercent();
50 *seconds = scePowerGetBatteryLifeTime() * 60;
51 } else {
52 *state = SDL_POWERSTATE_ON_BATTERY;
53 *percent = scePowerGetBatteryLifePercent();
54 *seconds = scePowerGetBatteryLifeTime() * 60;
55 }
56
57 return true; // always the definitive answer on VITA.
58}
59
60#endif // SDL_POWER_VITA
61#endif // SDL_POWER_DISABLED
diff --git a/contrib/SDL-3.2.8/src/power/windows/SDL_syspower.c b/contrib/SDL-3.2.8/src/power/windows/SDL_syspower.c
new file mode 100644
index 0000000..ab334f3
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/power/windows/SDL_syspower.c
@@ -0,0 +1,70 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifndef SDL_POWER_DISABLED
24#ifdef SDL_POWER_WINDOWS
25
26#include "../../core/windows/SDL_windows.h"
27
28bool SDL_GetPowerInfo_Windows(SDL_PowerState *state, int *seconds, int *percent)
29{
30 SYSTEM_POWER_STATUS status;
31 bool need_details = false;
32
33 // This API should exist back to Win95.
34 if (!GetSystemPowerStatus(&status)) {
35 // !!! FIXME: push GetLastError() into SDL_GetError()
36 *state = SDL_POWERSTATE_UNKNOWN;
37 } else if (status.BatteryFlag == 0xFF) { // unknown state
38 *state = SDL_POWERSTATE_UNKNOWN;
39 } else if (status.BatteryFlag & (1 << 7)) { // no battery
40 *state = SDL_POWERSTATE_NO_BATTERY;
41 } else if (status.BatteryFlag & (1 << 3)) { // charging
42 *state = SDL_POWERSTATE_CHARGING;
43 need_details = true;
44 } else if (status.ACLineStatus == 1) {
45 *state = SDL_POWERSTATE_CHARGED; // on AC, not charging.
46 need_details = true;
47 } else {
48 *state = SDL_POWERSTATE_ON_BATTERY; // not on AC.
49 need_details = true;
50 }
51
52 *percent = -1;
53 *seconds = -1;
54 if (need_details) {
55 const int pct = (int)status.BatteryLifePercent;
56 const int secs = (int)status.BatteryLifeTime;
57
58 if (pct != 255) { // 255 == unknown
59 *percent = (pct > 100) ? 100 : pct; // clamp between 0%, 100%
60 }
61 if (secs != 0xFFFFFFFF) { // ((DWORD)-1) == unknown
62 *seconds = secs;
63 }
64 }
65
66 return true; // always the definitive answer on Windows.
67}
68
69#endif // SDL_POWER_WINDOWS
70#endif // SDL_POWER_DISABLED