Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

First shot at Windows XInput haptics.

  • Loading branch information
icculus committed Mar 10, 2013
1 parent f0d5200 commit 16164dfc7540a5d9e9580fc44476c0d32f30ebe9
@@ -203,7 +203,7 @@ extern "C" {
* "0" - Disable XInput timer (only uses direct input)
* "1" - Enable XInput timer (the default)
*/
#define SD_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED"
#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED"


/**
@@ -24,10 +24,73 @@

#include "SDL_error.h"
#include "SDL_windows.h"
#include "SDL_assert.h"

#include <objbase.h> /* for CoInitialize/CoUninitialize */


XInputGetState_t SDL_XInputGetState = NULL;
XInputSetState_t SDL_XInputSetState = NULL;
XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
DWORD SDL_XInputVersion = 0;

static HANDLE s_pXInputDLL = 0;
static int s_XInputDLLRefCount = 0;

int
WIN_LoadXInputDLL(void)
{
DWORD version = 0;

if (s_pXInputDLL) {
SDL_assert(s_XInputDLLRefCount > 0);
s_XInputDLLRefCount++;
return 0; /* already loaded */
}

version = (1 << 16) | 4;
s_pXInputDLL = LoadLibrary( L"XInput1_4.dll" ); // 1.4 Ships with Windows 8.
if (!s_pXInputDLL) {
version = (1 << 16) | 3;
s_pXInputDLL = LoadLibrary( L"XInput1_3.dll" ); // 1.3 Ships with Vista and Win7, can be installed as a restributable component.
}
if (!s_pXInputDLL) {
s_pXInputDLL = LoadLibrary( L"bin\\XInput1_3.dll" );
}
if (!s_pXInputDLL) {
return -1;
}

SDL_assert(s_XInputDLLRefCount == 0);
SDL_XInputVersion = version;
s_XInputDLLRefCount = 1;

/* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */
SDL_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, (LPCSTR)100 );
SDL_XInputSetState = (XInputSetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputSetState" );
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetCapabilities" );
if ( !SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities ) {
WIN_UnloadXInputDLL();
return -1;
}

return 0;
}

void
WIN_UnloadXInputDLL(void)
{
if ( s_pXInputDLL ) {
SDL_assert(s_XInputDLLRefCount > 0);
if (--s_XInputDLLRefCount == 0) {
FreeLibrary( s_pXInputDLL );
s_pXInputDLL = NULL;
}
} else {
SDL_assert(s_XInputDLLRefCount == 0);
}
}

/* Sets an error message based on GetLastError() */
void
WIN_SetError(const char *prefix)
@@ -33,7 +33,7 @@
#define _WIN32_WINNT 0x501 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices(), 0x501 for raw input */

#include <windows.h>

#include <xinput.h>

/* Routines to convert from UTF8 to native Windows text */
#if UNICODE
@@ -51,6 +51,64 @@ extern void WIN_SetError(const char *prefix);
extern HRESULT WIN_CoInitialize(void);
extern void WIN_CoUninitialize(void);

/* typedef's for XInput structs we use */
typedef struct
{
WORD wButtons;
BYTE bLeftTrigger;
BYTE bRightTrigger;
SHORT sThumbLX;
SHORT sThumbLY;
SHORT sThumbRX;
SHORT sThumbRY;
DWORD dwPaddingReserved;
} XINPUT_GAMEPAD_EX;

typedef struct
{
DWORD dwPacketNumber;
XINPUT_GAMEPAD_EX Gamepad;
} XINPUT_STATE_EX;


/* Forward decl's for XInput API's we load dynamically and use if available */
typedef DWORD (WINAPI *XInputGetState_t)
(
DWORD dwUserIndex, // [in] Index of the gamer associated with the device
XINPUT_STATE_EX* pState // [out] Receives the current state
);

typedef DWORD (WINAPI *XInputSetState_t)
(
DWORD dwUserIndex, // [in] Index of the gamer associated with the device
XINPUT_VIBRATION* pVibration // [in, out] The vibration information to send to the controller
);

typedef DWORD (WINAPI *XInputGetCapabilities_t)
(
DWORD dwUserIndex, // [in] Index of the gamer associated with the device
DWORD dwFlags, // [in] Input flags that identify the device type
XINPUT_CAPABILITIES* pCapabilities // [out] Receives the capabilities
);

extern int WIN_LoadXInputDLL(void);
extern void WIN_UnloadXInputDLL(void);

extern XInputGetState_t SDL_XInputGetState;
extern XInputSetState_t SDL_XInputSetState;
extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
extern DWORD SDL_XInputVersion; // ((major << 16) & 0xFF00) | (minor & 0xFF)

#define XINPUTGETSTATE SDL_XInputGetState
#define XINPUTSETSTATE SDL_XInputSetState
#define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities
#define INVALID_XINPUT_USERID 255
#define SDL_XINPUT_MAX_DEVICES 4

#ifndef XINPUT_CAPS_FFB_SUPPORTED
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
#endif

#endif /* _INCLUDED_WINDOWS_H */

/* vi: set ts=4 sw=4 expandtab: */

0 comments on commit 16164df

Please sign in to comment.