SDL: joystick: Report battery on GIP controllers

From 7dd5e765df239986f78c9b0016e3f3023d885084 Mon Sep 17 00:00:00 2001
From: Vicki Pfau <[EMAIL REDACTED]>
Date: Thu, 5 Jun 2025 17:39:43 -0700
Subject: [PATCH] joystick: Report battery on GIP controllers

---
 src/joystick/hidapi/SDL_hidapi_gip.c | 56 +++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/src/joystick/hidapi/SDL_hidapi_gip.c b/src/joystick/hidapi/SDL_hidapi_gip.c
index 4b4afcc02404e..b20dbd41a101b 100644
--- a/src/joystick/hidapi/SDL_hidapi_gip.c
+++ b/src/joystick/hidapi/SDL_hidapi_gip.c
@@ -1412,17 +1412,71 @@ static bool GIP_HandleCommandStatusDevice(
     const Uint8 *bytes,
     int num_bytes)
 {
-    GIP_ExtendedStatus status = {{0}};
+    GIP_ExtendedStatus status;
+    SDL_Joystick *joystick = NULL;
+    SDL_PowerState power_state;
+    int power_percent = 0;
     int i;
 
     if (num_bytes < 1) {
         return false;
     }
+    SDL_zero(status);
     status.base.battery_level = bytes[0] & 3;
     status.base.battery_type = (bytes[0] >> 2) & 3;
     status.base.charge = (bytes[0] >> 4) & 3;
     status.base.power_level = (bytes[0] >> 6) & 3;
 
+    if (attachment->joystick) {
+        joystick = SDL_GetJoystickFromID(attachment->joystick);
+    }
+    if (joystick) {
+        switch (status.base.battery_level) {
+        case GIP_BATTERY_CRITICAL:
+            power_percent = 1;
+            break;
+        case GIP_BATTERY_LOW:
+            power_percent = 25;
+            break;
+        case GIP_BATTERY_MEDIUM:
+            power_percent = 50;
+            break;
+        case GIP_BATTERY_FULL:
+            power_percent = 100;
+            break;
+        }
+        switch (status.base.charge) {
+        case GIP_CHARGING:
+            if (status.base.battery_level == GIP_BATTERY_FULL) {
+                power_state = SDL_POWERSTATE_CHARGED;
+            } else {
+                power_state = SDL_POWERSTATE_CHARGING;
+            }
+            break;
+        case GIP_NOT_CHARGING:
+            power_state = SDL_POWERSTATE_ON_BATTERY;
+            break;
+        case GIP_CHARGE_ERROR:
+        default:
+            power_state = SDL_POWERSTATE_UNKNOWN;
+            break;
+        }
+
+        switch (status.base.battery_type) {
+        case GIP_BATTERY_ABSENT:
+            power_state = SDL_POWERSTATE_NO_BATTERY;
+            break;
+        case GIP_BATTERY_STANDARD:
+        case GIP_BATTERY_RECHARGEABLE:
+            break;
+        default:
+            power_state = SDL_POWERSTATE_UNKNOWN;
+            break;
+        }
+
+        SDL_SendJoystickPowerInfo(joystick, power_state, power_percent);
+    }
+
     if (num_bytes >= 4) {
         status.device_active = bytes[1] & 1;
         if (bytes[1] & 2) {