SDL - added new SDL_JoystickCurrentPowerLevel() API that returns the battery level of the selected joystick. Currently only implemented for XInput devices, other platforms are a TODO.
authorSam Lantinga <slouken@libsdl.org>
Wed, 30 Sep 2015 15:39:30 -0700
changeset 988426b595dea221
parent 9883 48cf7d652118
child 9885 3a25a7f73e5f
SDL - added new SDL_JoystickCurrentPowerLevel() API that returns the battery level of the selected joystick. Currently only implemented for XInput devices, other platforms are a TODO.

CR: Sam
include/SDL_joystick.h
src/core/windows/SDL_xinput.c
src/core/windows/SDL_xinput.h
src/joystick/SDL_joystick.c
src/joystick/SDL_joystick_c.h
src/joystick/SDL_sysjoystick.h
src/joystick/windows/SDL_xinputjoystick.c
     1.1 --- a/include/SDL_joystick.h	Wed Sep 30 15:38:30 2015 -0700
     1.2 +++ b/include/SDL_joystick.h	Wed Sep 30 15:39:30 2015 -0700
     1.3 @@ -71,6 +71,16 @@
     1.4  
     1.5  typedef Sint32 SDL_JoystickID;
     1.6  
     1.7 +typedef enum
     1.8 +{
     1.9 +    SDL_JOYSTICK_POWER_UNKNOWN = -1,
    1.10 +    SDL_JOYSTICK_POWER_EMPTY,
    1.11 +    SDL_JOYSTICK_POWER_LOW,
    1.12 +    SDL_JOYSTICK_POWER_MEDIUM,
    1.13 +    SDL_JOYSTICK_POWER_FULL,
    1.14 +    SDL_JOYSTICK_POWER_WIRED,
    1.15 +    SDL_JOYSTICK_POWER_MAX
    1.16 +} SDL_JoystickPowerLevel;
    1.17  
    1.18  /* Function prototypes */
    1.19  /**
    1.20 @@ -242,6 +252,11 @@
    1.21   */
    1.22  extern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick * joystick);
    1.23  
    1.24 +/**
    1.25 +*  Return the battery level of this joystick
    1.26 +*/
    1.27 +extern DECLSPEC SDL_JoystickPowerLevel SDLCALL SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick);
    1.28 +
    1.29  
    1.30  /* Ends C function definitions when using C++ */
    1.31  #ifdef __cplusplus
     2.1 --- a/src/core/windows/SDL_xinput.c	Wed Sep 30 15:38:30 2015 -0700
     2.2 +++ b/src/core/windows/SDL_xinput.c	Wed Sep 30 15:39:30 2015 -0700
     2.3 @@ -29,6 +29,7 @@
     2.4  XInputGetState_t SDL_XInputGetState = NULL;
     2.5  XInputSetState_t SDL_XInputSetState = NULL;
     2.6  XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
     2.7 +XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation = NULL;
     2.8  DWORD SDL_XInputVersion = 0;
     2.9  
    2.10  static HANDLE s_pXInputDLL = 0;
    2.11 @@ -55,6 +56,7 @@
    2.12      SDL_XInputGetState = (XInputGetState_t)XInputGetState;
    2.13      SDL_XInputSetState = (XInputSetState_t)XInputSetState;
    2.14      SDL_XInputGetCapabilities = (XInputGetCapabilities_t)XInputGetCapabilities;
    2.15 +    SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)XInputGetBatteryInformation;
    2.16  
    2.17      /* XInput 1.4 ships with Windows 8 and 8.1: */
    2.18      SDL_XInputVersion = (1 << 16) | 4;
    2.19 @@ -108,6 +110,7 @@
    2.20      }
    2.21      SDL_XInputSetState = (XInputSetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputSetState");
    2.22      SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetCapabilities");
    2.23 +    SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetBatteryInformation" );
    2.24      if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) {
    2.25          WIN_UnloadXInputDLL();
    2.26          return -1;
     3.1 --- a/src/core/windows/SDL_xinput.h	Wed Sep 30 15:38:30 2015 -0700
     3.2 +++ b/src/core/windows/SDL_xinput.h	Wed Sep 30 15:39:30 2015 -0700
     3.3 @@ -76,6 +76,29 @@
     3.4  #define XINPUT_GAMEPAD_GUIDE 0x0400
     3.5  #endif
     3.6  
     3.7 +#ifndef BATTERY_DEVTYPE_GAMEPAD
     3.8 +#define BATTERY_DEVTYPE_GAMEPAD         0x00
     3.9 +#endif
    3.10 +#ifndef BATTERY_TYPE_WIRED
    3.11 +#define BATTERY_TYPE_WIRED              0x01
    3.12 +#endif
    3.13 +
    3.14 +#ifndef BATTERY_TYPE_UNKNOWN
    3.15 +#define BATTERY_TYPE_UNKNOWN            0xFF
    3.16 +#endif
    3.17 +#ifndef BATTERY_LEVEL_EMPTY
    3.18 +#define BATTERY_LEVEL_EMPTY             0x00
    3.19 +#endif
    3.20 +#ifndef BATTERY_LEVEL_LOW
    3.21 +#define BATTERY_LEVEL_LOW               0x01
    3.22 +#endif
    3.23 +#ifndef BATTERY_LEVEL_MEDIUM
    3.24 +#define BATTERY_LEVEL_MEDIUM            0x02
    3.25 +#endif
    3.26 +#ifndef BATTERY_LEVEL_FULL
    3.27 +#define BATTERY_LEVEL_FULL              0x03
    3.28 +#endif
    3.29 +
    3.30  /* typedef's for XInput structs we use */
    3.31  typedef struct
    3.32  {
    3.33 @@ -95,6 +118,12 @@
    3.34      XINPUT_GAMEPAD_EX Gamepad;
    3.35  } XINPUT_STATE_EX;
    3.36  
    3.37 +typedef struct _XINPUT_BATTERY_INFORMATION
    3.38 +{
    3.39 +    BYTE BatteryType;
    3.40 +    BYTE BatteryLevel;
    3.41 +} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
    3.42 +
    3.43  /* Forward decl's for XInput API's we load dynamically and use if available */
    3.44  typedef DWORD (WINAPI *XInputGetState_t)
    3.45      (
    3.46 @@ -115,17 +144,26 @@
    3.47      XINPUT_CAPABILITIES* pCapabilities  /* [out] Receives the capabilities */
    3.48      );
    3.49  
    3.50 +typedef DWORD (WINAPI *XInputGetBatteryInformation_t)
    3.51 +    (
    3.52 +    _In_  DWORD                      dwUserIndex,
    3.53 +    _In_  BYTE                       devType,
    3.54 +    _Out_ XINPUT_BATTERY_INFORMATION *pBatteryInformation
    3.55 +    );
    3.56 +
    3.57  extern int WIN_LoadXInputDLL(void);
    3.58  extern void WIN_UnloadXInputDLL(void);
    3.59  
    3.60  extern XInputGetState_t SDL_XInputGetState;
    3.61  extern XInputSetState_t SDL_XInputSetState;
    3.62  extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
    3.63 +extern XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation;
    3.64  extern DWORD SDL_XInputVersion;  /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
    3.65  
    3.66  #define XINPUTGETSTATE          SDL_XInputGetState
    3.67  #define XINPUTSETSTATE          SDL_XInputSetState
    3.68  #define XINPUTGETCAPABILITIES   SDL_XInputGetCapabilities
    3.69 +#define XINPUTGETBATTERYINFORMATION   SDL_XInputGetBatteryInformation
    3.70  
    3.71  #endif /* HAVE_XINPUT_H */
    3.72  
     4.1 --- a/src/joystick/SDL_joystick.c	Wed Sep 30 15:38:30 2015 -0700
     4.2 +++ b/src/joystick/SDL_joystick.c	Wed Sep 30 15:39:30 2015 -0700
     4.3 @@ -178,6 +178,7 @@
     4.4      if (joystick->buttons) {
     4.5          SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
     4.6      }
     4.7 +    joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
     4.8  
     4.9      /* Add joystick to list */
    4.10      ++joystick->ref_count;
    4.11 @@ -619,10 +620,10 @@
    4.12      /* Make sure we're not getting garbage or duplicate events */
    4.13      if (button >= joystick->nbuttons) {
    4.14          return 0;
    4.15 -	}
    4.16 -	if (state == joystick->buttons[button]) {
    4.17 -		return 0;
    4.18 -	}
    4.19 +    }
    4.20 +    if (state == joystick->buttons[button]) {
    4.21 +        return 0;
    4.22 +    }
    4.23  
    4.24      /* We ignore events if we don't have keyboard focus, except for button
    4.25       * release. */
    4.26 @@ -825,4 +826,21 @@
    4.27  }
    4.28  
    4.29  
    4.30 +/* update the power level for this joystick */
    4.31 +void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
    4.32 +{
    4.33 +    joystick->epowerlevel = ePowerLevel;
    4.34 +}
    4.35 +
    4.36 +
    4.37 +/* return its power level */
    4.38 +SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
    4.39 +{
    4.40 +    if (!SDL_PrivateJoystickValid(joystick)) {
    4.41 +        return (SDL_JOYSTICK_POWER_UNKNOWN);
    4.42 +    }
    4.43 +    return joystick->epowerlevel;
    4.44 +}
    4.45 +
    4.46 +
    4.47  /* vi: set ts=4 sw=4 expandtab: */
     5.1 --- a/src/joystick/SDL_joystick_c.h	Wed Sep 30 15:38:30 2015 -0700
     5.2 +++ b/src/joystick/SDL_joystick_c.h	Wed Sep 30 15:39:30 2015 -0700
     5.3 @@ -41,6 +41,8 @@
     5.4                                    Uint8 hat, Uint8 value);
     5.5  extern int SDL_PrivateJoystickButton(SDL_Joystick * joystick,
     5.6                                       Uint8 button, Uint8 state);
     5.7 +extern void SDL_PrivateJoystickBatteryLevel( SDL_Joystick * joystick,
     5.8 +    SDL_JoystickPowerLevel ePowerLevel );
     5.9  
    5.10  /* Internal sanity checking functions */
    5.11  extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
     6.1 --- a/src/joystick/SDL_sysjoystick.h	Wed Sep 30 15:38:30 2015 -0700
     6.2 +++ b/src/joystick/SDL_sysjoystick.h	Wed Sep 30 15:39:30 2015 -0700
     6.3 @@ -54,6 +54,7 @@
     6.4      int ref_count;              /* Reference count for multiple opens */
     6.5  
     6.6      SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
     6.7 +    SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */
     6.8      struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
     6.9  };
    6.10  
     7.1 --- a/src/joystick/windows/SDL_xinputjoystick.c	Wed Sep 30 15:38:30 2015 -0700
     7.2 +++ b/src/joystick/windows/SDL_xinputjoystick.c	Wed Sep 30 15:39:30 2015 -0700
     7.3 @@ -221,8 +221,39 @@
     7.4      return 0;
     7.5  }
     7.6  
     7.7 +static void 
     7.8 +UpdateXInputJoystickBatteryInformation(SDL_Joystick * joystick, XINPUT_BATTERY_INFORMATION *pBatteryInformation)
     7.9 +{
    7.10 +    if ( pBatteryInformation->BatteryType != BATTERY_TYPE_UNKNOWN )
    7.11 +    {
    7.12 +        SDL_JoystickPowerLevel ePowerLevel = SDL_JOYSTICK_POWER_UNKNOWN;
    7.13 +        if (pBatteryInformation->BatteryType == BATTERY_TYPE_WIRED) {
    7.14 +            ePowerLevel = SDL_JOYSTICK_POWER_WIRED;
    7.15 +        } else {
    7.16 +            switch ( pBatteryInformation->BatteryLevel )
    7.17 +            {
    7.18 +            case BATTERY_LEVEL_EMPTY:
    7.19 +                ePowerLevel = SDL_JOYSTICK_POWER_EMPTY;
    7.20 +                break;
    7.21 +            case BATTERY_LEVEL_LOW:
    7.22 +                ePowerLevel = SDL_JOYSTICK_POWER_LOW;
    7.23 +                break;
    7.24 +            case BATTERY_LEVEL_MEDIUM:
    7.25 +                ePowerLevel = SDL_JOYSTICK_POWER_MEDIUM;
    7.26 +                break;
    7.27 +            default:
    7.28 +            case BATTERY_LEVEL_FULL:
    7.29 +                ePowerLevel = SDL_JOYSTICK_POWER_FULL;
    7.30 +                break;
    7.31 +            }
    7.32 +        }
    7.33 +
    7.34 +        SDL_PrivateJoystickBatteryLevel( joystick, ePowerLevel );
    7.35 +    }
    7.36 +}
    7.37 +
    7.38  static void
    7.39 -UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
    7.40 +UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION *pBatteryInformation)
    7.41  {
    7.42      static WORD s_XInputButtons[] = {
    7.43          XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
    7.44 @@ -244,10 +275,12 @@
    7.45      for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
    7.46          SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
    7.47      }
    7.48 +
    7.49 +    UpdateXInputJoystickBatteryInformation( joystick, pBatteryInformation );
    7.50  }
    7.51  
    7.52  static void
    7.53 -UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
    7.54 +UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION *pBatteryInformation)
    7.55  {
    7.56      static WORD s_XInputButtons[] = {
    7.57          XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
    7.58 @@ -283,6 +316,8 @@
    7.59          hat |= SDL_HAT_RIGHT;
    7.60      }
    7.61      SDL_PrivateJoystickHat(joystick, 0, hat);
    7.62 +
    7.63 +    UpdateXInputJoystickBatteryInformation( joystick, pBatteryInformation );
    7.64  }
    7.65  
    7.66  void
    7.67 @@ -290,6 +325,7 @@
    7.68  {
    7.69      HRESULT result;
    7.70      XINPUT_STATE_EX XInputState;
    7.71 +    XINPUT_BATTERY_INFORMATION XBatteryInformation;
    7.72  
    7.73      if (!XINPUTGETSTATE)
    7.74          return;
    7.75 @@ -301,12 +337,18 @@
    7.76          return;
    7.77      }
    7.78  
    7.79 +    SDL_zero( XBatteryInformation );
    7.80 +    if ( XINPUTGETBATTERYINFORMATION )
    7.81 +    {
    7.82 +        result = XINPUTGETBATTERYINFORMATION( joystick->hwdata->userid, BATTERY_DEVTYPE_GAMEPAD, &XBatteryInformation );
    7.83 +    }
    7.84 +
    7.85      /* only fire events if the data changed from last time */
    7.86      if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
    7.87          if (SDL_XInputUseOldJoystickMapping()) {
    7.88 -            UpdateXInputJoystickState_OLD(joystick, &XInputState);
    7.89 +            UpdateXInputJoystickState_OLD(joystick, &XInputState, &XBatteryInformation);
    7.90          } else {
    7.91 -            UpdateXInputJoystickState(joystick, &XInputState);
    7.92 +            UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation);
    7.93          }
    7.94          joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
    7.95      }