diff --git a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj
index 292a02866..fbcd94b6b 100644
--- a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj
+++ b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj
@@ -47,6 +47,7 @@
true
+
true
true
@@ -93,9 +94,14 @@
+
+
+
-
+
+
+
@@ -278,7 +284,9 @@
+
+
@@ -297,9 +305,15 @@
+
+
+
+
+
+
diff --git a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters
index a536f33a0..aa539d37e 100644
--- a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters
+++ b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters
@@ -247,9 +247,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -298,6 +295,27 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -672,6 +690,30 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
index 1607182ac..7665cc473 100644
--- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
+++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
@@ -86,7 +86,9 @@
+
+
@@ -105,9 +107,15 @@
+
+
+
+
+
+
@@ -173,6 +181,7 @@
true
+
true
true
@@ -219,10 +228,15 @@
+
+
+
-
+
+
+
diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
index fa973a057..502f92cf6 100644
--- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
+++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
@@ -381,6 +381,24 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
@@ -485,9 +503,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -683,5 +698,20 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
\ No newline at end of file
diff --git a/VisualC/SDL/SDL_VS2008.vcproj b/VisualC/SDL/SDL_VS2008.vcproj
index 5abfa6560..53db16dd5 100644
--- a/VisualC/SDL/SDL_VS2008.vcproj
+++ b/VisualC/SDL/SDL_VS2008.vcproj
@@ -371,6 +371,14 @@
+
+
+
+
@@ -419,10 +427,6 @@
RelativePath="..\..\include\SDL_egl.h"
>
-
-
@@ -499,10 +503,34 @@
RelativePath="..\..\include\SDL_opengl.h"
>
+
+
+
+
+
+
+
+
+
+
+
+
@@ -559,6 +587,54 @@
RelativePath="..\..\include\SDL_syswm.h"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -583,10 +659,6 @@
RelativePath="..\..\include\SDL_video.h"
>
-
-
-
-
@@ -824,6 +892,22 @@
RelativePath="..\..\src\render\SDL_d3dmath.h"
>
+
+
+
+
+
+
+
+
@@ -832,6 +916,10 @@
RelativePath="..\..\src\audio\directsound\SDL_directsound.h"
>
+
+
@@ -876,10 +964,6 @@
RelativePath="..\..\src\audio\dummy\SDL_dummyaudio.h"
>
-
-
@@ -1156,10 +1240,6 @@
RelativePath="..\..\src\filesystem\windows\SDL_sysfilesystem.c"
>
-
-
@@ -1296,6 +1376,22 @@
RelativePath="..\..\src\video\windows\SDL_windowsframebuffer.h"
>
+
+
+
+
+
+
+
+
@@ -1376,6 +1472,30 @@
RelativePath="..\..\src\audio\xaudio2\SDL_xaudio2.c"
>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VisualC/SDL/SDL_VS2010.vcxproj b/VisualC/SDL/SDL_VS2010.vcxproj
index dd368bbee..ba4137e3f 100644
--- a/VisualC/SDL/SDL_VS2010.vcxproj
+++ b/VisualC/SDL/SDL_VS2010.vcxproj
@@ -219,6 +219,8 @@
+
+
@@ -235,6 +237,7 @@
+
@@ -244,11 +247,18 @@
+
+
+
+
+
+
+
@@ -263,23 +273,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
@@ -322,7 +351,6 @@
-
@@ -348,10 +376,17 @@
+
+
+
+
+
+
+
@@ -416,7 +451,6 @@
-
@@ -444,7 +478,6 @@
-
diff --git a/VisualC/SDL/SDL_VS2012.vcxproj b/VisualC/SDL/SDL_VS2012.vcxproj
index 97dedf68c..1a1350890 100644
--- a/VisualC/SDL/SDL_VS2012.vcxproj
+++ b/VisualC/SDL/SDL_VS2012.vcxproj
@@ -223,6 +223,8 @@
+
+
@@ -239,6 +241,7 @@
+
@@ -248,11 +251,18 @@
+
+
+
+
+
+
+
@@ -267,23 +277,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
@@ -326,7 +355,6 @@
-
@@ -352,10 +380,17 @@
+
+
+
+
+
+
+
@@ -420,7 +455,6 @@
-
@@ -448,7 +482,6 @@
-
diff --git a/VisualC/SDL/SDL_VS2013.vcxproj b/VisualC/SDL/SDL_VS2013.vcxproj
index fa3d3346b..1ef810e49 100644
--- a/VisualC/SDL/SDL_VS2013.vcxproj
+++ b/VisualC/SDL/SDL_VS2013.vcxproj
@@ -223,6 +223,8 @@
+
+
@@ -239,6 +241,7 @@
+
@@ -248,11 +251,18 @@
+
+
+
+
+
+
+
@@ -267,23 +277,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
@@ -326,7 +355,6 @@
-
@@ -352,10 +380,17 @@
+
+
+
+
+
+
+
@@ -420,7 +455,6 @@
-
@@ -448,7 +482,6 @@
-
diff --git a/configure b/configure
index fb81a2db1..a598f36bf 100755
--- a/configure
+++ b/configure
@@ -22112,18 +22112,50 @@ if test "x$ac_cv_header_dinput_h" = xyes; then :
fi
- ac_fn_c_check_header_mongrel "$LINENO" "xaudio2.h" "ac_cv_header_xaudio2_h" "$ac_includes_default"
-if test "x$ac_cv_header_xaudio2_h" = xyes; then :
- have_xaudio2=yes
-fi
-
-
ac_fn_c_check_header_mongrel "$LINENO" "dxgi.h" "ac_cv_header_dxgi_h" "$ac_includes_default"
if test "x$ac_cv_header_dxgi_h" = xyes; then :
have_dxgi=yes
fi
+ ac_fn_c_check_header_mongrel "$LINENO" "xaudio2.h" "ac_cv_header_xaudio2_h" "$ac_includes_default"
+if test "x$ac_cv_header_xaudio2_h" = xyes; then :
+ have_xaudio2=yes
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "xinput.h" "ac_cv_header_xinput_h" "$ac_includes_default"
+if test "x$ac_cv_header_xinput_h" = xyes; then :
+ have_xinput=yes
+fi
+
+
+
+ if test x$have_ddraw = xyes; then
+
+$as_echo "#define HAVE_DDRAW_H 1" >>confdefs.h
+
+ fi
+ if test x$have_dinput = xyes; then
+
+$as_echo "#define HAVE_DINPUT_H 1" >>confdefs.h
+
+ fi
+ if test x$have_dsound = xyes; then
+
+$as_echo "#define HAVE_DSOUND_H 1" >>confdefs.h
+
+ fi
+ if test x$have_dxgi = xyes; then
+
+$as_echo "#define HAVE_DXGI_H 1" >>confdefs.h
+
+ fi
+ if test x$have_xinput = xyes; then
+
+$as_echo "#define HAVE_XINPUT_H 1" >>confdefs.h
+
+ fi
SUMMARY_video="${SUMMARY_video} directx"
SUMMARY_audio="${SUMMARY_audio} directx"
@@ -22981,11 +23013,6 @@ $as_echo "#define SDL_VIDEO_RENDER_D3D11 1" >>confdefs.h
fi
fi
- if test x$have_dxgi = xyes; then
-
-$as_echo "#define HAVE_DXGI_H 1" >>confdefs.h
-
- fi
# Set up files for the audio library
if test x$enable_audio = xyes; then
@@ -23008,25 +23035,38 @@ $as_echo "#define SDL_AUDIO_DRIVER_XAUDIO2 1" >>confdefs.h
fi
# Set up files for the joystick library
if test x$enable_joystick = xyes; then
- if test x$have_dinput = xyes; then
+ if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+ if test x$have_xinput = xyes; then
+
+$as_echo "#define SDL_JOYSTICK_XINPUT 1" >>confdefs.h
+
+ fi
+ if test x$have_dinput = xyes; then
$as_echo "#define SDL_JOYSTICK_DINPUT 1" >>confdefs.h
- SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_dxjoystick.c"
- EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+ fi
else
$as_echo "#define SDL_JOYSTICK_WINMM 1" >>confdefs.h
- SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_mmjoystick.c"
fi
+ SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
have_joystick=yes
fi
if test x$enable_haptic = xyes; then
- if test x$have_dinput = xyes; then
+ if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+ if test x$have_xinput = xyes; then
+
+$as_echo "#define SDL_HAPTIC_XINPUT 1" >>confdefs.h
+
+ fi
+ if test x$have_dinput = xyes; then
$as_echo "#define SDL_HAPTIC_DINPUT 1" >>confdefs.h
+ fi
SOURCES="$SOURCES $srcdir/src/haptic/windows/SDL_syshaptic.c"
have_haptic=yes
fi
diff --git a/configure.in b/configure.in
index efb371a2b..42aec1d3f 100644
--- a/configure.in
+++ b/configure.in
@@ -2496,8 +2496,25 @@ AC_HELP_STRING([--enable-directx], [use DirectX for Windows audio/video [[defaul
AC_CHECK_HEADER(ddraw.h, have_ddraw=yes)
AC_CHECK_HEADER(dsound.h, have_dsound=yes)
AC_CHECK_HEADER(dinput.h, have_dinput=yes)
- AC_CHECK_HEADER(xaudio2.h, have_xaudio2=yes)
AC_CHECK_HEADER(dxgi.h, have_dxgi=yes)
+ AC_CHECK_HEADER(xaudio2.h, have_xaudio2=yes)
+ AC_CHECK_HEADER(xinput.h, have_xinput=yes)
+
+ if test x$have_ddraw = xyes; then
+ AC_DEFINE(HAVE_DDRAW_H, 1, [ ])
+ fi
+ if test x$have_dinput = xyes; then
+ AC_DEFINE(HAVE_DINPUT_H, 1, [ ])
+ fi
+ if test x$have_dsound = xyes; then
+ AC_DEFINE(HAVE_DSOUND_H, 1, [ ])
+ fi
+ if test x$have_dxgi = xyes; then
+ AC_DEFINE(HAVE_DXGI_H, 1, [ ])
+ fi
+ if test x$have_xinput = xyes; then
+ AC_DEFINE(HAVE_XINPUT_H, 1, [ ])
+ fi
SUMMARY_video="${SUMMARY_video} directx"
SUMMARY_audio="${SUMMARY_audio} directx"
@@ -2927,9 +2944,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
AC_DEFINE(SDL_VIDEO_RENDER_D3D11, 1, [ ])
fi
fi
- if test x$have_dxgi = xyes; then
- AC_DEFINE(HAVE_DXGI_H, 1, [ ])
- fi
# Set up files for the audio library
if test x$enable_audio = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_WINMM, 1, [ ])
@@ -2946,19 +2960,28 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
fi
# Set up files for the joystick library
if test x$enable_joystick = xyes; then
- if test x$have_dinput = xyes; then
- AC_DEFINE(SDL_JOYSTICK_DINPUT, 1, [ ])
- SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_dxjoystick.c"
- EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+ if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+ if test x$have_xinput = xyes; then
+ AC_DEFINE(SDL_JOYSTICK_XINPUT, 1, [ ])
+ fi
+ if test x$have_dinput = xyes; then
+ AC_DEFINE(SDL_JOYSTICK_DINPUT, 1, [ ])
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+ fi
else
AC_DEFINE(SDL_JOYSTICK_WINMM, 1, [ ])
- SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_mmjoystick.c"
fi
+ SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
have_joystick=yes
fi
if test x$enable_haptic = xyes; then
- if test x$have_dinput = xyes; then
- AC_DEFINE(SDL_HAPTIC_DINPUT, 1, [ ])
+ if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+ if test x$have_xinput = xyes; then
+ AC_DEFINE(SDL_HAPTIC_XINPUT, 1, [ ])
+ fi
+ if test x$have_dinput = xyes; then
+ AC_DEFINE(SDL_HAPTIC_DINPUT, 1, [ ])
+ fi
SOURCES="$SOURCES $srcdir/src/haptic/windows/SDL_syshaptic.c"
have_haptic=yes
fi
diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in
index 6d2ac9d1c..ea25249ac 100644
--- a/include/SDL_config.h.in
+++ b/include/SDL_config.h.in
@@ -51,7 +51,11 @@
#undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET
#undef HAVE_PTHREAD_SPINLOCK
+#undef HAVE_DDRAW_H
+#undef HAVE_DINPUT_H
+#undef HAVE_DSOUND_H
#undef HAVE_DXGI_H
+#undef HAVE_XINPUT_H
/* Comment this if you want to build without any C library requirements */
#undef HAVE_LIBC
@@ -232,6 +236,7 @@
#undef SDL_INPUT_TSLIB
#undef SDL_JOYSTICK_HAIKU
#undef SDL_JOYSTICK_DINPUT
+#undef SDL_JOYSTICK_XINPUT
#undef SDL_JOYSTICK_DUMMY
#undef SDL_JOYSTICK_IOKIT
#undef SDL_JOYSTICK_LINUX
@@ -243,6 +248,7 @@
#undef SDL_HAPTIC_LINUX
#undef SDL_HAPTIC_IOKIT
#undef SDL_HAPTIC_DINPUT
+#undef SDL_HAPTIC_XINPUT
/* Enable various shared object loading systems */
#undef SDL_LOADSO_HAIKU
diff --git a/include/SDL_config_windows.h b/include/SDL_config_windows.h
index 29e5a47fe..8bc7ffe09 100644
--- a/include/SDL_config_windows.h
+++ b/include/SDL_config_windows.h
@@ -76,7 +76,11 @@ typedef unsigned int uintptr_t;
# define SIZEOF_VOIDP 4
#endif
+#define HAVE_DDRAW_H 1
+#define HAVE_DINPUT_H 1
+#define HAVE_DSOUND_H 1
#define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
/* This is disabled by default to avoid C runtime dependencies and manifest requirements */
#ifdef HAVE_LIBC
@@ -158,7 +162,9 @@ typedef unsigned int uintptr_t;
/* Enable various input drivers */
#define SDL_JOYSTICK_DINPUT 1
+#define SDL_JOYSTICK_XINPUT 1
#define SDL_HAPTIC_DINPUT 1
+#define SDL_HAPTIC_XINPUT 1
/* Enable various shared object loading systems */
#define SDL_LOADSO_WINDOWS 1
diff --git a/include/SDL_config_winrt.h b/include/SDL_config_winrt.h
index 97c51405f..74ebfbcf2 100644
--- a/include/SDL_config_winrt.h
+++ b/include/SDL_config_winrt.h
@@ -78,6 +78,7 @@ typedef unsigned int uintptr_t;
/* Useful headers */
#define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
#define HAVE_LIBC 1
#define HAVE_STDIO_H 1
#define STDC_HEADERS 1
@@ -148,13 +149,12 @@ typedef unsigned int uintptr_t;
#define SDL_AUDIO_DRIVER_DUMMY 1
/* Enable various input drivers */
-// TODO, WinRT: Get haptic support working
-#define SDL_HAPTIC_DISABLED 1
-
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
#define SDL_JOYSTICK_DISABLED 1
+#define SDL_HAPTIC_DISABLED 1
#else
#define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_XINPUT 1
#endif
/* Enable various shared object loading systems */
diff --git a/src/audio/directsound/SDL_directsound.h b/src/audio/directsound/SDL_directsound.h
index b873391fb..ae7faa451 100644
--- a/src/audio/directsound/SDL_directsound.h
+++ b/src/audio/directsound/SDL_directsound.h
@@ -23,7 +23,7 @@
#ifndef _SDL_directsound_h
#define _SDL_directsound_h
-#include "directx.h"
+#include "../../core/windows/SDL_directx.h"
#include "../SDL_sysaudio.h"
diff --git a/src/audio/directsound/directx.h b/src/core/windows/SDL_directx.h
similarity index 86%
rename from src/audio/directsound/directx.h
rename to src/core/windows/SDL_directx.h
index 472a0ee0e..f37bccef2 100644
--- a/src/audio/directsound/directx.h
+++ b/src/core/windows/SDL_directx.h
@@ -18,13 +18,14 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
+#include "../../SDL_internal.h"
-#ifndef _directx_h
-#define _directx_h
+#ifndef _SDL_directx_h
+#define _SDL_directx_h
/* Include all of the DirectX 8.0 headers and adds any necessary tweaks */
-#include "../../core/windows/SDL_windows.h"
+#include "SDL_windows.h"
#include
#ifndef WIN32
#define WIN32
@@ -91,12 +92,20 @@
/* We need these defines to mark what version of DirectX API we use */
#define DIRECTDRAW_VERSION 0x0700
#define DIRECTSOUND_VERSION 0x0800
-#define DIRECTINPUT_VERSION 0x0500
+#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
+#ifdef HAVE_DDRAW_H
#include
+#endif
+#ifdef HAVE_DSOUND_H
#include
+#endif
+#ifdef HAVE_DINPUT_H
#include
+#else
+typedef struct { int unused; } DIDEVICEINSTANCE;
+#endif
-#endif /* _directx_h */
+#endif /* _SDL_directx_h */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/core/windows/SDL_xinput.c b/src/core/windows/SDL_xinput.c
new file mode 100644
index 000000000..9b2a54fef
--- /dev/null
+++ b/src/core/windows/SDL_xinput.c
@@ -0,0 +1,94 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_assert.h"
+#include "SDL_xinput.h"
+
+
+#ifdef HAVE_XINPUT_H
+
+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 redistributable 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);
+ }
+}
+
+#endif /* HAVE_XINPUT_H */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/windows/SDL_dxjoystick_c.h b/src/core/windows/SDL_xinput.h
similarity index 67%
rename from src/joystick/windows/SDL_dxjoystick_c.h
rename to src/core/windows/SDL_xinput.h
index e0739587c..721c3811b 100644
--- a/src/joystick/windows/SDL_dxjoystick_c.h
+++ b/src/core/windows/SDL_xinput.h
@@ -20,29 +20,13 @@
*/
#include "../../SDL_internal.h"
-#ifndef SDL_JOYSTICK_DINPUT_H
+#ifndef _SDL_xinput_h
+#define _SDL_xinput_h
-/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
- * A. Formiga's WINMM driver.
- *
- * Hats and sliders are completely untested; the app I'm writing this for mostly
- * doesn't use them and I don't own any joysticks with them.
- *
- * We don't bother to use event notification here. It doesn't seem to work
- * with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
- * let it return 0 events. */
+#ifdef HAVE_XINPUT_H
-#include "../../core/windows/SDL_windows.h"
-
-#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
-#include
-#define COBJMACROS
-#include
-#include
+#include "SDL_windows.h"
#include
-#include
-#include
-
#ifndef XUSER_MAX_COUNT
#define XUSER_MAX_COUNT 4
@@ -142,45 +126,9 @@ 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 XUSER_INDEX_ANY
-#define SDL_XINPUT_MAX_DEVICES XUSER_MAX_COUNT
-#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */
+#endif /* HAVE_XINPUT_H */
+#endif /* _SDL_xinput_h */
-/* local types */
-typedef enum Type
-{ BUTTON, AXIS, HAT } Type;
-
-typedef struct input_t
-{
- /* DirectInput offset for this input type: */
- DWORD ofs;
-
- /* Button, axis or hat: */
- Type type;
-
- /* SDL input offset: */
- Uint8 num;
-} input_t;
-
-/* The private structure used to keep track of a joystick */
-struct joystick_hwdata
-{
- LPDIRECTINPUTDEVICE8 InputDevice;
- DIDEVCAPS Capabilities;
- int buffered;
- SDL_JoystickGUID guid;
-
- input_t Inputs[MAX_INPUTS];
- int NumInputs;
- int NumSliders;
- SDL_bool removed;
- SDL_bool send_remove_event;
- SDL_bool bXInputDevice; /* SDL_TRUE if this device supports using the xinput API rather than DirectInput */
- SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
- Uint8 userid; /* XInput userid index for this joystick */
- DWORD dwPacketNumber;
-};
-
-#endif /* SDL_JOYSTICK_DINPUT_H */
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/haptic/windows/SDL_syshaptic.c b/src/haptic/windows/SDL_dinputhaptic.c
similarity index 58%
rename from src/haptic/windows/SDL_syshaptic.c
rename to src/haptic/windows/SDL_dinputhaptic.c
index c5a901149..e96fe1bea 100644
--- a/src/haptic/windows/SDL_syshaptic.c
+++ b/src/haptic/windows/SDL_dinputhaptic.c
@@ -20,73 +20,16 @@
*/
#include "../../SDL_internal.h"
-#ifdef SDL_HAPTIC_DINPUT
-
-#include "SDL_assert.h"
-#include "SDL_thread.h"
-#include "SDL_mutex.h"
-#include "SDL_timer.h"
-#include "SDL_hints.h"
+#include "SDL_error.h"
#include "SDL_haptic.h"
+#include "SDL_timer.h"
+#include "SDL_windowshaptic_c.h"
+#include "SDL_dinputhaptic_c.h"
#include "../SDL_syshaptic.h"
-#include "SDL_joystick.h"
-#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
-#include "../../joystick/windows/SDL_dxjoystick_c.h" /* For joystick hwdata */
-
-#include "SDL_syshaptic_c.h"
-
-/*
- * List of available haptic devices.
- */
-typedef struct SDL_hapticlist_item
-{
- DIDEVICEINSTANCE instance;
- char *name;
- SDL_Haptic *haptic;
- DIDEVCAPS capabilities;
- Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
- Uint8 userid; /* XInput userid index for this joystick */
- struct SDL_hapticlist_item *next;
-} SDL_hapticlist_item;
+#include "../../joystick/windows/SDL_windowsjoystick_c.h"
-/*
- * Haptic system hardware data.
- */
-struct haptic_hwdata
-{
- LPDIRECTINPUTDEVICE8 device;
- DWORD axes[3]; /* Axes to use. */
- SDL_bool is_joystick; /* Device is loaded as joystick. */
- Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
- Uint8 userid; /* XInput userid index for this joystick */
- SDL_Thread *thread;
- SDL_mutex *mutex;
- volatile Uint32 stopTicks;
- volatile int stopThread;
-};
-
-
-/*
- * Haptic system effect data.
- */
-struct haptic_hweffect
-{
- DIEFFECT effect;
- LPDIRECTINPUTEFFECT ref;
- XINPUT_VIBRATION vibration;
-};
-
-
-/*
- * Internal stuff.
- */
-static SDL_bool coinitialized = SDL_FALSE;
-static LPDIRECTINPUT8 dinput = NULL;
-static SDL_bool loaded_xinput = SDL_FALSE;
-static SDL_hapticlist_item *SDL_hapticlist = NULL;
-static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
-static int numhaptics = 0;
+#if SDL_HAPTIC_DINPUT
/*
* External stuff.
@@ -95,29 +38,10 @@ extern HWND SDL_HelperWindow;
/*
- * Prototypes.
+ * Internal stuff.
*/
-static int DI_SetError(const char *str, HRESULT err);
-static int DI_GUIDIsSame(const GUID * a, const GUID * b);
-static int SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic,
- DIDEVICEINSTANCE instance);
-static int SDL_SYS_HapticOpenFromDevice8(SDL_Haptic * haptic,
- LPDIRECTINPUTDEVICE8 device8,
- SDL_bool is_joystick);
-static int SDL_SYS_HapticOpenFromXInput(SDL_Haptic * haptic, const Uint8 userid);
-static DWORD DIGetTriggerButton(Uint16 button);
-static int SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir,
- int naxes);
-static int SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
- SDL_HapticEffect * src);
-static void SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type);
-static REFGUID SDL_SYS_HapticEffectType(SDL_HapticEffect * effect);
-static int SDLCALL SDL_RunXInputHaptic(void *arg);
-
-/* Callbacks. */
-static BOOL CALLBACK EnumHapticsCallback(const DIDEVICEINSTANCE *
- pdidInstance, VOID * pContext);
-static BOOL CALLBACK DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv);
+static SDL_bool coinitialized = SDL_FALSE;
+static LPDIRECTINPUT8 dinput = NULL;
/*
@@ -133,7 +57,6 @@ DI_SetError(const char *str, HRESULT err)
return SDL_SetError("Haptic error %s", str);
}
-
/*
* Checks to see if two GUID are the same.
*/
@@ -143,14 +66,20 @@ DI_GUIDIsSame(const GUID * a, const GUID * b)
return (SDL_memcmp(a, b, sizeof (GUID)) == 0);
}
-
/*
- * Initializes the haptic subsystem.
+ * Callback to find the haptic devices.
*/
-int
-SDL_SYS_HapticInit(void)
+static BOOL CALLBACK
+EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
+{
+ (void) pContext;
+ SDL_DINPUT_MaybeAddDevice(pdidInstance);
+ return DIENUM_CONTINUE; /* continue enumerating */
+}
+
+int
+SDL_DINPUT_HapticInit(void)
{
- const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
HRESULT ret;
HINSTANCE instance;
@@ -166,7 +95,7 @@ SDL_SYS_HapticInit(void)
coinitialized = SDL_TRUE;
ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
- &IID_IDirectInput8, (LPVOID) & dinput);
+ &IID_IDirectInput8, (LPVOID)& dinput);
if (FAILED(ret)) {
SDL_SYS_HapticQuit();
return DI_SetError("CoCreateInstance", ret);
@@ -177,7 +106,7 @@ SDL_SYS_HapticInit(void)
if (instance == NULL) {
SDL_SYS_HapticQuit();
return SDL_SetError("GetModuleHandle() failed with error code %d.",
- GetLastError());
+ GetLastError());
}
ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
if (FAILED(ret)) {
@@ -187,33 +116,20 @@ SDL_SYS_HapticInit(void)
/* Look for haptic devices. */
ret = IDirectInput8_EnumDevices(dinput,
- 0,
- EnumHapticsCallback,
- NULL,
- DIEDFL_FORCEFEEDBACK |
- DIEDFL_ATTACHEDONLY);
+ 0,
+ EnumHapticsCallback,
+ NULL,
+ DIEDFL_FORCEFEEDBACK |
+ DIEDFL_ATTACHEDONLY);
if (FAILED(ret)) {
SDL_SYS_HapticQuit();
return DI_SetError("Enumerating DirectInput devices", ret);
}
-
- if (!env || SDL_atoi(env)) {
- loaded_xinput = (WIN_LoadXInputDLL() == 0);
- }
-
- if (loaded_xinput) {
- DWORD i;
- for (i = 0; i < SDL_XINPUT_MAX_DEVICES; i++) {
- XInputHaptic_MaybeAddDevice(i);
- }
- }
-
- return numhaptics;
+ return 0;
}
-
int
-DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
+SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
{
HRESULT ret;
LPDIRECTINPUTDEVICE8 device;
@@ -227,7 +143,7 @@ DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
/* Make sure we don't already have it */
for (item = SDL_hapticlist; item; item = item->next) {
- if ( (!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof (*pdidInstance)) == 0) ) {
+ if ((!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0)) {
return -1; /* Already added */
}
}
@@ -241,7 +157,7 @@ DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
/* Get capabilities. */
SDL_zero(capabilities);
- capabilities.dwSize = sizeof (DIDEVCAPS);
+ capabilities.dwSize = sizeof(DIDEVCAPS);
ret = IDirectInputDevice8_GetCapabilities(device, &capabilities);
IDirectInputDevice8_Release(device);
if (FAILED(ret)) {
@@ -265,25 +181,14 @@ DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
}
/* Copy the instance over, useful for creating devices. */
- SDL_memcpy(&item->instance, pdidInstance, sizeof (DIDEVICEINSTANCE));
- SDL_memcpy(&item->capabilities, &capabilities, sizeof (capabilities));
+ SDL_memcpy(&item->instance, pdidInstance, sizeof(DIDEVICEINSTANCE));
+ SDL_memcpy(&item->capabilities, &capabilities, sizeof(capabilities));
- if (SDL_hapticlist_tail == NULL) {
- SDL_hapticlist = SDL_hapticlist_tail = item;
- } else {
- SDL_hapticlist_tail->next = item;
- SDL_hapticlist_tail = item;
- }
-
- /* Device has been added. */
- ++numhaptics;
-
- return numhaptics;
+ return SDL_SYS_AddHapticDevice(item);
}
-
int
-DirectInputHaptic_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
+SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
{
SDL_hapticlist_item *item;
SDL_hapticlist_item *prev = NULL;
@@ -293,205 +198,15 @@ DirectInputHaptic_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
}
for (item = SDL_hapticlist; item != NULL; item = item->next) {
- if ( (!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof (*pdidInstance)) == 0) ) {
+ if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
/* found it, remove it. */
- const int retval = item->haptic ? item->haptic->index : -1;
- if (prev != NULL) {
- prev->next = item->next;
- } else {
- SDL_assert(SDL_hapticlist == item);
- SDL_hapticlist = item->next;
- }
- if (item == SDL_hapticlist_tail) {
- SDL_hapticlist_tail = prev;
- }
- --numhaptics;
- /* !!! TODO: Send a haptic remove event? */
- SDL_free(item);
- return retval;
+ return SDL_SYS_RemoveHapticDevice(prev, item);
}
prev = item;
}
-
return -1;
}
-
-int
-XInputHaptic_MaybeAddDevice(const DWORD dwUserid)
-{
- const Uint8 userid = (Uint8) dwUserid;
- SDL_hapticlist_item *item;
- XINPUT_VIBRATION state;
-
- if ((!loaded_xinput) || (dwUserid >= SDL_XINPUT_MAX_DEVICES)) {
- return -1;
- }
-
- /* Make sure we don't already have it */
- for (item = SDL_hapticlist; item; item = item->next) {
- if ((item->bXInputHaptic) && (item->userid == userid)) {
- return -1; /* Already added */
- }
- }
-
- SDL_zero(state);
- if (XINPUTSETSTATE(dwUserid, &state) != ERROR_SUCCESS) {
- return -1; /* no force feedback on this device. */
- }
-
- item = (SDL_hapticlist_item *)SDL_malloc( sizeof(SDL_hapticlist_item));
- if (item == NULL) {
- return SDL_OutOfMemory();
- }
-
- SDL_zerop(item);
-
- /* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */
- {
- char buf[64];
- SDL_snprintf(buf, sizeof (buf), "XInput Controller #%u", (unsigned int) (userid+1));
- item->name = SDL_strdup(buf);
- }
-
- if (!item->name) {
- SDL_free(item);
- return -1;
- }
-
- /* Copy the instance over, useful for creating devices. */
- item->bXInputHaptic = 1;
- item->userid = userid;
-
- if (SDL_hapticlist_tail == NULL) {
- SDL_hapticlist = SDL_hapticlist_tail = item;
- } else {
- SDL_hapticlist_tail->next = item;
- SDL_hapticlist_tail = item;
- }
-
- /* Device has been added. */
- ++numhaptics;
-
- return numhaptics;
-}
-
-
-int
-XInputHaptic_MaybeRemoveDevice(const DWORD dwUserid)
-{
- const Uint8 userid = (Uint8) dwUserid;
- SDL_hapticlist_item *item;
- SDL_hapticlist_item *prev = NULL;
-
- if ((!loaded_xinput) || (dwUserid >= SDL_XINPUT_MAX_DEVICES)) {
- return -1;
- }
-
- for (item = SDL_hapticlist; item != NULL; item = item->next) {
- if ((item->bXInputHaptic) && (item->userid == userid)) {
- /* found it, remove it. */
- const int retval = item->haptic ? item->haptic->index : -1;
- if (prev != NULL) {
- prev->next = item->next;
- } else {
- SDL_assert(SDL_hapticlist == item);
- SDL_hapticlist = item->next;
- }
- if (item == SDL_hapticlist_tail) {
- SDL_hapticlist_tail = prev;
- }
- --numhaptics;
- /* !!! TODO: Send a haptic remove event? */
- SDL_free(item);
- return retval;
- }
- prev = item;
- }
-
- return -1;
-}
-
-
-/*
- * Callback to find the haptic devices.
- */
-static BOOL CALLBACK
-EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
-{
- (void) pContext;
- DirectInputHaptic_MaybeAddDevice(pdidInstance);
- return DIENUM_CONTINUE; /* continue enumerating */
-}
-
-
-int
-SDL_SYS_NumHaptics()
-{
- return numhaptics;
-}
-
-static SDL_hapticlist_item *
-HapticByDevIndex(int device_index)
-{
- SDL_hapticlist_item *item = SDL_hapticlist;
-
- if ((device_index < 0) || (device_index >= numhaptics)) {
- return NULL;
- }
-
- while (device_index > 0) {
- SDL_assert(item != NULL);
- --device_index;
- item = item->next;
- }
-
- return item;
-}
-
-/*
- * Return the name of a haptic device, does not need to be opened.
- */
-const char *
-SDL_SYS_HapticName(int index)
-{
- SDL_hapticlist_item *item = HapticByDevIndex(index);
- return item->name;
-}
-
-
-/*
- * Callback to get all supported effects.
- */
-#define EFFECT_TEST(e,s) \
-if (DI_GUIDIsSame(&pei->guid, &(e))) \
- haptic->supported |= (s)
-static BOOL CALLBACK
-DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
-{
- /* Prepare the haptic device. */
- SDL_Haptic *haptic = (SDL_Haptic *) pv;
-
- /* Get supported. */
- EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
- EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
- EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
- EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
- EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
- EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
- EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
- /* !!! FIXME: put this back when we have more bits in 2.1 */
- /* EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); */
- EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
- EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
- EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
- EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
-
- /* Check for more. */
- return DIENUM_CONTINUE;
-}
-
-
/*
* Callback to get supported axes.
*/
@@ -531,118 +246,39 @@ DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
return DIENUM_CONTINUE;
}
-
/*
- * Opens the haptic device from the file descriptor.
- *
- * Steps:
- * - Open temporary DirectInputDevice interface.
- * - Create DirectInputDevice8 interface.
- * - Release DirectInputDevice interface.
- * - Call SDL_SYS_HapticOpenFromDevice8
+ * Callback to get all supported effects.
*/
-static int
-SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic, DIDEVICEINSTANCE instance)
+#define EFFECT_TEST(e,s) \
+if (DI_GUIDIsSame(&pei->guid, &(e))) \
+ haptic->supported |= (s)
+static BOOL CALLBACK
+DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
{
- HRESULT ret;
- int ret2;
- LPDIRECTINPUTDEVICE8 device;
- LPDIRECTINPUTDEVICE8 device8;
+ /* Prepare the haptic device. */
+ SDL_Haptic *haptic = (SDL_Haptic *) pv;
- /* Open the device */
- ret = IDirectInput8_CreateDevice(dinput, &instance.guidInstance,
- &device, NULL);
- if (FAILED(ret)) {
- DI_SetError("Creating DirectInput device", ret);
- return -1;
- }
+ /* Get supported. */
+ EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
+ EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
+ EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
+ EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
+ EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
+ EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
+ EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
+ /* !!! FIXME: put this back when we have more bits in 2.1 */
+ /* EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); */
+ EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
+ EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
+ EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
+ EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
- /* Now get the IDirectInputDevice8 interface, instead. */
- ret = IDirectInputDevice8_QueryInterface(device,
- &IID_IDirectInputDevice8,
- (LPVOID *) &device8);
- /* Done with the temporary one now. */
- IDirectInputDevice8_Release(device);
- if (FAILED(ret)) {
- DI_SetError("Querying DirectInput interface", ret);
- return -1;
- }
-
- ret2 = SDL_SYS_HapticOpenFromDevice8(haptic, device8, SDL_FALSE);
- if (ret2 < 0) {
- IDirectInputDevice8_Release(device8);
- return -1;
- }
-
- return 0;
+ /* Check for more. */
+ return DIENUM_CONTINUE;
}
-static int
-SDL_SYS_HapticOpenFromXInput(SDL_Haptic *haptic, const Uint8 userid)
-{
- char threadName[32];
- XINPUT_VIBRATION vibration = { 0, 0 }; /* stop any current vibration */
- XINPUTSETSTATE(userid, &vibration);
-
- haptic->supported = SDL_HAPTIC_LEFTRIGHT;
-
- haptic->neffects = 1;
- haptic->nplaying = 1;
-
- /* Prepare effects memory. */
- haptic->effects = (struct haptic_effect *)
- SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
- if (haptic->effects == NULL) {
- return SDL_OutOfMemory();
- }
- /* Clear the memory */
- SDL_memset(haptic->effects, 0,
- sizeof(struct haptic_effect) * haptic->neffects);
-
- haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata));
- if (haptic->hwdata == NULL) {
- SDL_free(haptic->effects);
- haptic->effects = NULL;
- return SDL_OutOfMemory();
- }
- SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
-
- haptic->hwdata->bXInputHaptic = 1;
- haptic->hwdata->userid = userid;
-
- haptic->hwdata->mutex = SDL_CreateMutex();
- if (haptic->hwdata->mutex == NULL) {
- SDL_free(haptic->effects);
- SDL_free(haptic->hwdata);
- haptic->effects = NULL;
- return SDL_SetError("Couldn't create XInput haptic mutex");
- }
-
- SDL_snprintf(threadName, sizeof (threadName), "SDLXInputDev%d", (int) userid);
-
-#if defined(__WIN32__) && !defined(HAVE_LIBC) /* !!! FIXME: this is nasty. */
- #undef SDL_CreateThread
- #if SDL_DYNAMIC_API
- haptic->hwdata->thread = SDL_CreateThread_REAL(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
- #else
- haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
- #endif
-#else
- haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata);
-#endif
- if (haptic->hwdata->thread == NULL) {
- SDL_DestroyMutex(haptic->hwdata->mutex);
- SDL_free(haptic->effects);
- SDL_free(haptic->hwdata);
- haptic->effects = NULL;
- return SDL_SetError("Couldn't create XInput haptic thread");
- }
-
- return 0;
- }
-
/*
- * Opens the haptic device from the file descriptor.
+ * Opens the haptic device.
*
* Steps:
* - Set cooperative level.
@@ -652,8 +288,7 @@ SDL_SYS_HapticOpenFromXInput(SDL_Haptic *haptic, const Uint8 userid)
* - Get supported features.
*/
static int
-SDL_SYS_HapticOpenFromDevice8(SDL_Haptic * haptic,
- LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
+SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
{
HRESULT ret;
DIPROPDWORD dipdw;
@@ -788,203 +423,106 @@ SDL_SYS_HapticOpenFromDevice8(SDL_Haptic * haptic,
acquire_err:
IDirectInputDevice8_Unacquire(haptic->hwdata->device);
return -1;
-
}
-
-/*
- * Opens a haptic device for usage.
- */
int
-SDL_SYS_HapticOpen(SDL_Haptic * haptic)
+SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
{
- SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
- return (item->bXInputHaptic) ? SDL_SYS_HapticOpenFromXInput(haptic, item->userid) : SDL_SYS_HapticOpenFromInstance(haptic, item->instance);
+ HRESULT ret;
+ LPDIRECTINPUTDEVICE8 device;
+ LPDIRECTINPUTDEVICE8 device8;
+
+ /* Open the device */
+ ret = IDirectInput8_CreateDevice(dinput, &item->instance.guidInstance,
+ &device, NULL);
+ if (FAILED(ret)) {
+ DI_SetError("Creating DirectInput device", ret);
+ return -1;
+ }
+
+ /* Now get the IDirectInputDevice8 interface, instead. */
+ ret = IDirectInputDevice8_QueryInterface(device,
+ &IID_IDirectInputDevice8,
+ (LPVOID *)&device8);
+ /* Done with the temporary one now. */
+ IDirectInputDevice8_Release(device);
+ if (FAILED(ret)) {
+ DI_SetError("Querying DirectInput interface", ret);
+ return -1;
+ }
+
+ if (SDL_DINPUT_HapticOpenFromDevice(haptic, device8, SDL_FALSE) < 0) {
+ IDirectInputDevice8_Release(device8);
+ return -1;
+ }
+ return 0;
}
-
-/*
- * Opens a haptic device from first mouse it finds for usage.
- */
int
-SDL_SYS_HapticMouse(void)
+SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ HRESULT ret;
+ DIDEVICEINSTANCE hap_instance, joy_instance;
+
+ hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
+ joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
+
+ /* Get the device instances. */
+ ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
+ &hap_instance);
+ if (FAILED(ret)) {
+ return 0;
+ }
+ ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
+ &joy_instance);
+ if (FAILED(ret)) {
+ return 0;
+ }
+
+ return DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance);
+}
+
+int
+SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
{
SDL_hapticlist_item *item;
int index = 0;
+ HRESULT ret;
+ DIDEVICEINSTANCE joy_instance;
- /* Grab the first mouse haptic device we find. */
+ joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
+ ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
+ if (FAILED(ret)) {
+ return -1;
+ }
+
+ /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
for (item = SDL_hapticlist; item != NULL; item = item->next) {
- SDL_assert(index >= 0);
- if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
- return index;
+ if (!item->bXInputHaptic && DI_GUIDIsSame(&item->instance.guidInstance, &joy_instance.guidInstance)) {
+ haptic->index = index;
+ return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
}
++index;
}
+ SDL_SetError("Couldn't find joystick in haptic device list");
return -1;
}
-
-/*
- * Checks to see if a joystick has haptic features.
- */
-int
-SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
-{
- const struct joystick_hwdata *hwdata = joystick->hwdata;
- return ( (hwdata->bXInputHaptic) ||
- ((hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) != 0) );
-}
-
-
-/*
- * Checks to see if the haptic device and joystick are in reality the same.
- */
-int
-SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
-{
- if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
- return 0; /* one is XInput, one is not; not the same device. */
- } else if (joystick->hwdata->bXInputHaptic) { /* XInput */
- return (haptic->hwdata->userid == joystick->hwdata->userid);
- } else { /* DirectInput */
- HRESULT ret;
- DIDEVICEINSTANCE hap_instance, joy_instance;
-
- hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
- joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
-
- /* Get the device instances. */
- ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
- &hap_instance);
- if (FAILED(ret)) {
- return 0;
- }
- ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
- &joy_instance);
- if (FAILED(ret)) {
- return 0;
- }
-
- if (DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance))
- return 1;
- }
-
- return 0;
-}
-
-
-/*
- * Opens a SDL_Haptic from a SDL_Joystick.
- */
-int
-SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
-{
- SDL_hapticlist_item *item;
- int index = 0;
-
- /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
- if (joystick->hwdata->bXInputDevice) {
- const Uint8 userid = joystick->hwdata->userid;
- for (item = SDL_hapticlist; item != NULL; item = item->next) {
- if ((item->bXInputHaptic) && (item->userid == userid)) {
- SDL_assert(joystick->hwdata->bXInputHaptic);
- haptic->index = index;
- return SDL_SYS_HapticOpenFromXInput(haptic, userid);
- }
- ++index;
- }
- } else {
- HRESULT idret;
- DIDEVICEINSTANCE joy_instance;
-
- joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
- idret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
- if (FAILED(idret)) {
- return -1;
- }
-
- for (item = SDL_hapticlist; item != NULL; item = item->next) {
- if (DI_GUIDIsSame(&item->instance.guidInstance, &joy_instance.guidInstance)) {
- haptic->index = index;
- return SDL_SYS_HapticOpenFromDevice8(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
- }
- ++index;
- }
- }
-
- /* No match to our haptic list */
- return -1;
-}
-
-
-/*
- * Closes the haptic device.
- */
void
-SDL_SYS_HapticClose(SDL_Haptic * haptic)
+SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
{
- if (haptic->hwdata) {
+ IDirectInputDevice8_Unacquire(haptic->hwdata->device);
- /* Free effects. */
- SDL_free(haptic->effects);
- haptic->effects = NULL;
- haptic->neffects = 0;
-
- /* Clean up */
- if (haptic->hwdata->bXInputHaptic) {
- haptic->hwdata->stopThread = 1;
- SDL_WaitThread(haptic->hwdata->thread, NULL);
- SDL_DestroyMutex(haptic->hwdata->mutex);
- } else {
- IDirectInputDevice8_Unacquire(haptic->hwdata->device);
- /* Only release if isn't grabbed by a joystick. */
- if (haptic->hwdata->is_joystick == 0) {
- IDirectInputDevice8_Release(haptic->hwdata->device);
- }
- }
-
- /* Free */
- SDL_free(haptic->hwdata);
- haptic->hwdata = NULL;
+ /* Only release if isn't grabbed by a joystick. */
+ if (haptic->hwdata->is_joystick == 0) {
+ IDirectInputDevice8_Release(haptic->hwdata->device);
}
}
-
-/*
- * Clean up after system specific haptic stuff
- */
void
-SDL_SYS_HapticQuit(void)
+SDL_DINPUT_HapticQuit(void)
{
- SDL_hapticlist_item *item;
- SDL_hapticlist_item *next = NULL;
- SDL_Haptic *hapticitem = NULL;
-
- extern SDL_Haptic *SDL_haptics;
- for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
- if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
- /* we _have_ to stop the thread before we free the XInput DLL! */
- hapticitem->hwdata->stopThread = 1;
- SDL_WaitThread(hapticitem->hwdata->thread, NULL);
- hapticitem->hwdata->thread = NULL;
- }
- }
-
- for (item = SDL_hapticlist; item; item = next) {
- /* Opened and not closed haptics are leaked, this is on purpose.
- * Close your haptic devices after usage. */
- /* !!! FIXME: (...is leaking on purpose a good idea?) */
- next = item->next;
- SDL_free(item->name);
- SDL_free(item);
- }
-
- if (loaded_xinput) {
- WIN_UnloadXInputDLL();
- loaded_xinput = SDL_FALSE;
- }
-
if (dinput != NULL) {
IDirectInput8_Release(dinput);
dinput = NULL;
@@ -996,7 +534,6 @@ SDL_SYS_HapticQuit(void)
}
}
-
/*
* Converts an SDL trigger button to an DIEFFECT trigger button.
*/
@@ -1120,8 +657,7 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
dest->rgdwAxes = axes;
}
-
- /* The big type handling switch, even bigger then Linux's version. */
+ /* The big type handling switch, even bigger than Linux's version. */
switch (src->type) {
case SDL_HAPTIC_CONSTANT:
hap_constant = &src->constant;
@@ -1143,8 +679,7 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */
/* Direction. */
- if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes)
- < 0) {
+ if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) {
return -1;
}
@@ -1319,8 +854,7 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
dest->dwStartDelay = hap_custom->delay * 1000; /* In microseconds. */
/* Direction. */
- if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) <
- 0) {
+ if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) < 0) {
return -1;
}
@@ -1338,7 +872,6 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
break;
-
default:
return SDL_SetError("Haptic: Unknown effect type.");
}
@@ -1372,7 +905,6 @@ SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type)
effect->rglDirection = NULL;
}
-
/*
* Gets the effect type from the generic SDL haptic effect wrapper.
*/
@@ -1421,36 +953,15 @@ SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
return NULL;
}
}
-
-
-/*
- * Creates a new haptic effect.
- */
int
-SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
- SDL_HapticEffect * base)
+SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
{
HRESULT ret;
REFGUID type = SDL_SYS_HapticEffectType(base);
- if ((type == NULL) && (!haptic->hwdata->bXInputHaptic)) {
+ if (type == NULL) {
SDL_SetError("Haptic: Unknown effect type.");
- goto err_hweffect;
- }
-
- /* Alloc the effect. */
- effect->hweffect = (struct haptic_hweffect *)
- SDL_malloc(sizeof(struct haptic_hweffect));
- if (effect->hweffect == NULL) {
- SDL_OutOfMemory();
- goto err_hweffect;
- }
-
- SDL_zerop(effect->hweffect);
-
- if (haptic->hwdata->bXInputHaptic) {
- SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
- return SDL_SYS_HapticUpdateEffect(haptic, effect, base);
+ return -1;
}
/* Get the effect. */
@@ -1460,8 +971,8 @@ SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
/* Create the actual effect. */
ret = IDirectInputDevice8_CreateEffect(haptic->hwdata->device, type,
- &effect->hweffect->effect,
- &effect->hweffect->ref, NULL);
+ &effect->hweffect->effect,
+ &effect->hweffect->ref, NULL);
if (FAILED(ret)) {
DI_SetError("Unable to create effect", ret);
goto err_effectdone;
@@ -1469,40 +980,18 @@ SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
return 0;
- err_effectdone:
+err_effectdone:
SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, base->type);
- err_hweffect:
- SDL_free(effect->hweffect);
- effect->hweffect = NULL;
return -1;
}
-
-/*
- * Updates an effect.
- */
int
-SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
- struct haptic_effect *effect,
- SDL_HapticEffect * data)
+SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
{
HRESULT ret;
DWORD flags;
DIEFFECT temp;
- if (haptic->hwdata->bXInputHaptic) {
- XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
- SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT);
- vib->wLeftMotorSpeed = data->leftright.large_magnitude;
- vib->wRightMotorSpeed = data->leftright.small_magnitude;
- SDL_LockMutex(haptic->hwdata->mutex);
- if (haptic->hwdata->stopTicks) { /* running right now? Update it. */
- XINPUTSETSTATE(haptic->hwdata->userid, vib);
- }
- SDL_UnlockMutex(haptic->hwdata->mutex);
- return 0;
- }
-
/* Get the effect. */
SDL_memset(&temp, 0, sizeof(DIEFFECT));
if (SDL_SYS_ToDIEFFECT(haptic, &temp, data) < 0) {
@@ -1510,7 +999,7 @@ SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
}
/* Set the flags. Might be worthwhile to diff temp with loaded effect and
- * only change those parameters. */
+ * only change those parameters. */
flags = DIEP_DIRECTION |
DIEP_DURATION |
DIEP_ENVELOPE |
@@ -1532,110 +1021,58 @@ SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
return 0;
- err_update:
+err_update:
SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
return -1;
}
-
-/*
- * Runs an effect.
- */
int
-SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
- Uint32 iterations)
+SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
{
HRESULT ret;
DWORD iter;
- if (haptic->hwdata->bXInputHaptic) {
- XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
- SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
- SDL_LockMutex(haptic->hwdata->mutex);
- if(effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY) {
- haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY;
- } else if ((!effect->effect.leftright.length) || (!iterations)) {
- /* do nothing. Effect runs for zero milliseconds. */
- } else {
- haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
- if ((haptic->hwdata->stopTicks == SDL_HAPTIC_INFINITY) || (haptic->hwdata->stopTicks == 0)) {
- haptic->hwdata->stopTicks = 1; /* fix edge cases. */
- }
- }
- SDL_UnlockMutex(haptic->hwdata->mutex);
- return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
- }
-
/* Check if it's infinite. */
if (iterations == SDL_HAPTIC_INFINITY) {
iter = INFINITE;
- } else
+ } else {
iter = iterations;
+ }
/* Run the effect. */
ret = IDirectInputEffect_Start(effect->hweffect->ref, iter, 0);
if (FAILED(ret)) {
return DI_SetError("Running the effect", ret);
}
-
return 0;
}
-
-/*
- * Stops an effect.
- */
int
-SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
{
HRESULT ret;
- if (haptic->hwdata->bXInputHaptic) {
- XINPUT_VIBRATION vibration = { 0, 0 };
- SDL_LockMutex(haptic->hwdata->mutex);
- haptic->hwdata->stopTicks = 0;
- SDL_UnlockMutex(haptic->hwdata->mutex);
- return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
- }
-
ret = IDirectInputEffect_Stop(effect->hweffect->ref);
if (FAILED(ret)) {
return DI_SetError("Unable to stop effect", ret);
}
-
return 0;
}
-
-/*
- * Frees the effect.
- */
void
-SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
{
HRESULT ret;
- if (haptic->hwdata->bXInputHaptic) {
- SDL_SYS_HapticStopEffect(haptic, effect);
- } else {
- ret = IDirectInputEffect_Unload(effect->hweffect->ref);
- if (FAILED(ret)) {
- DI_SetError("Removing effect from the device", ret);
- }
- SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect,
- effect->effect.type);
+ ret = IDirectInputEffect_Unload(effect->hweffect->ref);
+ if (FAILED(ret)) {
+ DI_SetError("Removing effect from the device", ret);
}
- SDL_free(effect->hweffect);
- effect->hweffect = NULL;
+ SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, effect->effect.type);
}
-
-/*
- * Gets the status of a haptic effect.
- */
int
-SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
- struct haptic_effect *effect)
+SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
{
HRESULT ret;
DWORD status;
@@ -1650,12 +1087,8 @@ SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
return SDL_TRUE;
}
-
-/*
- * Sets the gain.
- */
int
-SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
+SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
{
HRESULT ret;
DIPROPDWORD dipdw;
@@ -1669,20 +1102,15 @@ SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
/* Try to set the autocenter. */
ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
- DIPROP_FFGAIN, &dipdw.diph);
+ DIPROP_FFGAIN, &dipdw.diph);
if (FAILED(ret)) {
return DI_SetError("Setting gain", ret);
}
-
return 0;
}
-
-/*
- * Sets the autocentering.
- */
int
-SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
{
HRESULT ret;
DIPROPDWORD dipdw;
@@ -1697,116 +1125,169 @@ SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
/* Try to set the autocenter. */
ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
- DIPROP_AUTOCENTER, &dipdw.diph);
+ DIPROP_AUTOCENTER, &dipdw.diph);
if (FAILED(ret)) {
return DI_SetError("Setting autocenter", ret);
}
-
return 0;
}
-
-/*
- * Pauses the device.
- */
int
-SDL_SYS_HapticPause(SDL_Haptic * haptic)
+SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
{
HRESULT ret;
/* Pause the device. */
ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
- DISFFC_PAUSE);
+ DISFFC_PAUSE);
if (FAILED(ret)) {
return DI_SetError("Pausing the device", ret);
}
-
return 0;
}
-
-/*
- * Pauses the device.
- */
int
-SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
+SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
{
HRESULT ret;
/* Unpause the device. */
ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
- DISFFC_CONTINUE);
+ DISFFC_CONTINUE);
if (FAILED(ret)) {
return DI_SetError("Pausing the device", ret);
}
-
return 0;
}
-
-/*
- * Stops all the playing effects on the device.
- */
int
-SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
+SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
{
HRESULT ret;
- if (haptic->hwdata->bXInputHaptic) {
- XINPUT_VIBRATION vibration = { 0, 0 };
- SDL_LockMutex(haptic->hwdata->mutex);
- haptic->hwdata->stopTicks = 0;
- SDL_UnlockMutex(haptic->hwdata->mutex);
- return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
- }
-
/* Try to stop the effects. */
ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
- DISFFC_STOPALL);
+ DISFFC_STOPALL);
if (FAILED(ret)) {
return DI_SetError("Stopping the device", ret);
}
-
return 0;
}
+#else /* !SDL_HAPTIC_DINPUT */
-/* !!! FIXME: this is a hack, remove this later. */
-/* Since XInput doesn't offer a way to vibrate for X time, we hook into
- * SDL_PumpEvents() to check if it's time to stop vibrating with some
- * frequency.
- * In practice, this works for 99% of use cases. But in an ideal world,
- * we do this in a separate thread so that:
- * - we aren't bound to when the app chooses to pump the event queue.
- * - we aren't adding more polling to the event queue
- * - we can emulate all the haptic effects correctly (start on a delay,
- * mix multiple effects, etc).
- *
- * Mostly, this is here to get rumbling to work, and all the other features
- * are absent in the XInput path for now. :(
- */
-static int SDLCALL
-SDL_RunXInputHaptic(void *arg)
+
+int
+SDL_DINPUT_HapticInit(void)
{
- struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;
-
- while (!hwdata->stopThread) {
- SDL_Delay(50);
- SDL_LockMutex(hwdata->mutex);
- /* If we're currently running and need to stop... */
- if (hwdata->stopTicks) {
- if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_TICKS_PASSED(SDL_GetTicks(), hwdata->stopTicks)) {
- XINPUT_VIBRATION vibration = { 0, 0 };
- hwdata->stopTicks = 0;
- XINPUTSETSTATE(hwdata->userid, &vibration);
- }
- }
- SDL_UnlockMutex(hwdata->mutex);
- }
-
return 0;
}
+int
+SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ return SDL_Unsupported();
+}
+
+void
+SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
+{
+}
+
+void
+SDL_DINPUT_HapticQuit(void)
+{
+}
+
+int
+SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ return SDL_Unsupported();
+}
+
+void
+SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+}
+
+int
+SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
#endif /* SDL_HAPTIC_DINPUT */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/haptic/windows/SDL_dinputhaptic_c.h b/src/haptic/windows/SDL_dinputhaptic_c.h
new file mode 100644
index 000000000..9801fe272
--- /dev/null
+++ b/src/haptic/windows/SDL_dinputhaptic_c.h
@@ -0,0 +1,47 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_haptic.h"
+#include "SDL_windowshaptic_c.h"
+
+
+extern int SDL_DINPUT_HapticInit(void);
+extern int SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance);
+extern int SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance);
+extern int SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
+extern int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern void SDL_DINPUT_HapticClose(SDL_Haptic * haptic);
+extern void SDL_DINPUT_HapticQuit(void);
+extern int SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base);
+extern int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data);
+extern int SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations);
+extern int SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern void SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain);
+extern int SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter);
+extern int SDL_DINPUT_HapticPause(SDL_Haptic * haptic);
+extern int SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic);
+extern int SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic);
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/haptic/windows/SDL_windowshaptic.c b/src/haptic/windows/SDL_windowshaptic.c
new file mode 100644
index 000000000..26095dc58
--- /dev/null
+++ b/src/haptic/windows/SDL_windowshaptic.c
@@ -0,0 +1,445 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
+
+#include "SDL_assert.h"
+#include "SDL_thread.h"
+#include "SDL_mutex.h"
+#include "SDL_timer.h"
+#include "SDL_hints.h"
+#include "SDL_haptic.h"
+#include "../SDL_syshaptic.h"
+#include "SDL_joystick.h"
+#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
+#include "../../joystick/windows/SDL_windowsjoystick_c.h" /* For joystick hwdata */
+#include "../../joystick/windows/SDL_xinputjoystick_c.h" /* For xinput rumble */
+
+#include "SDL_windowshaptic_c.h"
+#include "SDL_dinputhaptic_c.h"
+#include "SDL_xinputhaptic_c.h"
+
+
+/*
+ * Internal stuff.
+ */
+SDL_hapticlist_item *SDL_hapticlist = NULL;
+static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
+static int numhaptics = 0;
+
+
+/*
+ * Initializes the haptic subsystem.
+ */
+int
+SDL_SYS_HapticInit(void)
+{
+ if (SDL_DINPUT_HapticInit() < 0) {
+ return -1;
+ }
+ if (SDL_XINPUT_HapticInit() < 0) {
+ return -1;
+ }
+ return numhaptics;
+}
+
+int
+SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
+{
+ if (SDL_hapticlist_tail == NULL) {
+ SDL_hapticlist = SDL_hapticlist_tail = item;
+ } else {
+ SDL_hapticlist_tail->next = item;
+ SDL_hapticlist_tail = item;
+ }
+
+ /* Device has been added. */
+ ++numhaptics;
+
+ return numhaptics;
+}
+
+int
+SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
+{
+ const int retval = item->haptic ? item->haptic->index : -1;
+ if (prev != NULL) {
+ prev->next = item->next;
+ } else {
+ SDL_assert(SDL_hapticlist == item);
+ SDL_hapticlist = item->next;
+ }
+ if (item == SDL_hapticlist_tail) {
+ SDL_hapticlist_tail = prev;
+ }
+ --numhaptics;
+ /* !!! TODO: Send a haptic remove event? */
+ SDL_free(item);
+ return retval;
+}
+
+int
+SDL_SYS_NumHaptics()
+{
+ return numhaptics;
+}
+
+static SDL_hapticlist_item *
+HapticByDevIndex(int device_index)
+{
+ SDL_hapticlist_item *item = SDL_hapticlist;
+
+ if ((device_index < 0) || (device_index >= numhaptics)) {
+ return NULL;
+ }
+
+ while (device_index > 0) {
+ SDL_assert(item != NULL);
+ --device_index;
+ item = item->next;
+ }
+ return item;
+}
+
+/*
+ * Return the name of a haptic device, does not need to be opened.
+ */
+const char *
+SDL_SYS_HapticName(int index)
+{
+ SDL_hapticlist_item *item = HapticByDevIndex(index);
+ return item->name;
+}
+
+/*
+ * Opens a haptic device for usage.
+ */
+int
+SDL_SYS_HapticOpen(SDL_Haptic * haptic)
+{
+ SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
+ if (item->bXInputHaptic) {
+ return SDL_XINPUT_HapticOpen(haptic, item);
+ } else {
+ return SDL_DINPUT_HapticOpen(haptic, item);
+ }
+}
+
+
+/*
+ * Opens a haptic device from first mouse it finds for usage.
+ */
+int
+SDL_SYS_HapticMouse(void)
+{
+#if SDL_HAPTIC_DINPUT
+ SDL_hapticlist_item *item;
+ int index = 0;
+
+ /* Grab the first mouse haptic device we find. */
+ for (item = SDL_hapticlist; item != NULL; item = item->next) {
+ if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
+ return index;
+ }
+ ++index;
+ }
+#endif /* SDL_HAPTIC_DINPUT */
+ return -1;
+}
+
+
+/*
+ * Checks to see if a joystick has haptic features.
+ */
+int
+SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
+{
+ const struct joystick_hwdata *hwdata = joystick->hwdata;
+#if SDL_HAPTIC_XINPUT
+ if (hwdata->bXInputHaptic) {
+ return 1;
+ }
+#endif
+#if SDL_HAPTIC_DINPUT
+ if (hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Checks to see if the haptic device and joystick are in reality the same.
+ */
+int
+SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
+ return 0; /* one is XInput, one is not; not the same device. */
+ } else if (joystick->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
+ } else {
+ return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
+ }
+}
+
+/*
+ * Opens a SDL_Haptic from a SDL_Joystick.
+ */
+int
+SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ if (joystick->hwdata->bXInputDevice) {
+ return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick);
+ } else {
+ return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
+ }
+}
+
+/*
+ * Closes the haptic device.
+ */
+void
+SDL_SYS_HapticClose(SDL_Haptic * haptic)
+{
+ if (haptic->hwdata) {
+
+ /* Free effects. */
+ SDL_free(haptic->effects);
+ haptic->effects = NULL;
+ haptic->neffects = 0;
+
+ /* Clean up */
+ if (haptic->hwdata->bXInputHaptic) {
+ SDL_XINPUT_HapticClose(haptic);
+ } else {
+ SDL_DINPUT_HapticClose(haptic);
+ }
+
+ /* Free */
+ SDL_free(haptic->hwdata);
+ haptic->hwdata = NULL;
+ }
+}
+
+/*
+ * Clean up after system specific haptic stuff
+ */
+void
+SDL_SYS_HapticQuit(void)
+{
+ SDL_hapticlist_item *item;
+ SDL_hapticlist_item *next = NULL;
+ SDL_Haptic *hapticitem = NULL;
+
+ extern SDL_Haptic *SDL_haptics;
+ for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
+ if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
+ /* we _have_ to stop the thread before we free the XInput DLL! */
+ hapticitem->hwdata->stopThread = 1;
+ SDL_WaitThread(hapticitem->hwdata->thread, NULL);
+ hapticitem->hwdata->thread = NULL;
+ }
+ }
+
+ for (item = SDL_hapticlist; item; item = next) {
+ /* Opened and not closed haptics are leaked, this is on purpose.
+ * Close your haptic devices after usage. */
+ /* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */
+ next = item->next;
+ SDL_free(item->name);
+ SDL_free(item);
+ }
+
+ SDL_XINPUT_HapticQuit();
+ SDL_DINPUT_HapticQuit();
+}
+
+/*
+ * Creates a new haptic effect.
+ */
+int
+SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
+ SDL_HapticEffect * base)
+{
+ int result;
+
+ /* Alloc the effect. */
+ effect->hweffect = (struct haptic_hweffect *)
+ SDL_malloc(sizeof(struct haptic_hweffect));
+ if (effect->hweffect == NULL) {
+ SDL_OutOfMemory();
+ return -1;
+ }
+ SDL_zerop(effect->hweffect);
+
+ if (haptic->hwdata->bXInputHaptic) {
+ result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
+ } else {
+ result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
+ }
+ if (result < 0) {
+ SDL_free(effect->hweffect);
+ effect->hweffect = NULL;
+ }
+ return result;
+}
+
+/*
+ * Updates an effect.
+ */
+int
+SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
+ struct haptic_effect *effect,
+ SDL_HapticEffect * data)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
+ } else {
+ return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
+ }
+}
+
+/*
+ * Runs an effect.
+ */
+int
+SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
+ Uint32 iterations)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
+ } else {
+ return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
+ }
+}
+
+/*
+ * Stops an effect.
+ */
+int
+SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticStopEffect(haptic, effect);
+ } else {
+ return SDL_DINPUT_HapticStopEffect(haptic, effect);
+ }
+}
+
+/*
+ * Frees the effect.
+ */
+void
+SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ SDL_XINPUT_HapticDestroyEffect(haptic, effect);
+ } else {
+ SDL_DINPUT_HapticDestroyEffect(haptic, effect);
+ }
+ SDL_free(effect->hweffect);
+ effect->hweffect = NULL;
+}
+
+/*
+ * Gets the status of a haptic effect.
+ */
+int
+SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
+ struct haptic_effect *effect)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
+ } else {
+ return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
+ }
+}
+
+/*
+ * Sets the gain.
+ */
+int
+SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticSetGain(haptic, gain);
+ } else {
+ return SDL_DINPUT_HapticSetGain(haptic, gain);
+ }
+}
+
+/*
+ * Sets the autocentering.
+ */
+int
+SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
+ } else {
+ return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
+ }
+}
+
+/*
+ * Pauses the device.
+ */
+int
+SDL_SYS_HapticPause(SDL_Haptic * haptic)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticPause(haptic);
+ } else {
+ return SDL_DINPUT_HapticPause(haptic);
+ }
+}
+
+/*
+ * Pauses the device.
+ */
+int
+SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticUnpause(haptic);
+ } else {
+ return SDL_DINPUT_HapticUnpause(haptic);
+ }
+}
+
+/*
+ * Stops all the playing effects on the device.
+ */
+int
+SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
+{
+ if (haptic->hwdata->bXInputHaptic) {
+ return SDL_XINPUT_HapticStopAll(haptic);
+ } else {
+ return SDL_DINPUT_HapticStopAll(haptic);
+ }
+}
+
+#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/haptic/windows/SDL_windowshaptic_c.h b/src/haptic/windows/SDL_windowshaptic_c.h
new file mode 100644
index 000000000..a978c2448
--- /dev/null
+++ b/src/haptic/windows/SDL_windowshaptic_c.h
@@ -0,0 +1,88 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef _SDL_windowshaptic_c_h
+#define _SDL_windowshaptic_c_h
+
+#include "SDL_thread.h"
+
+#include "../../core/windows/SDL_directx.h"
+#include "../../core/windows/SDL_xinput.h"
+
+/*
+ * Haptic system hardware data.
+ */
+struct haptic_hwdata
+{
+#if SDL_HAPTIC_DINPUT
+ LPDIRECTINPUTDEVICE8 device;
+#endif
+ DWORD axes[3]; /* Axes to use. */
+ SDL_bool is_joystick; /* Device is loaded as joystick. */
+ Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
+ Uint8 userid; /* XInput userid index for this joystick */
+ SDL_Thread *thread;
+ SDL_mutex *mutex;
+ volatile Uint32 stopTicks;
+ volatile int stopThread;
+};
+
+
+/*
+ * Haptic system effect data.
+ */
+struct haptic_hweffect
+{
+#if SDL_HAPTIC_DINPUT
+ DIEFFECT effect;
+ LPDIRECTINPUTEFFECT ref;
+#endif
+#if SDL_HAPTIC_XINPUT
+ XINPUT_VIBRATION vibration;
+#endif
+};
+
+/*
+* List of available haptic devices.
+*/
+typedef struct SDL_hapticlist_item
+{
+ char *name;
+ SDL_Haptic *haptic;
+#if SDL_HAPTIC_DINPUT
+ DIDEVICEINSTANCE instance;
+ DIDEVCAPS capabilities;
+#endif
+ SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
+ Uint8 userid; /* XInput userid index for this joystick */
+ struct SDL_hapticlist_item *next;
+} SDL_hapticlist_item;
+
+extern SDL_hapticlist_item *SDL_hapticlist;
+
+extern int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item);
+extern int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item);
+
+#endif /* _SDL_windowshaptic_c_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
+
diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c
new file mode 100644
index 000000000..2e76a9592
--- /dev/null
+++ b/src/haptic/windows/SDL_xinputhaptic.c
@@ -0,0 +1,491 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_assert.h"
+#include "SDL_error.h"
+#include "SDL_haptic.h"
+#include "SDL_hints.h"
+#include "SDL_timer.h"
+#include "SDL_windowshaptic_c.h"
+#include "SDL_xinputhaptic_c.h"
+#include "../SDL_syshaptic.h"
+#include "../../core/windows/SDL_xinput.h"
+#include "../../joystick/windows/SDL_windowsjoystick_c.h"
+
+
+#if SDL_HAPTIC_XINPUT
+
+/*
+ * Internal stuff.
+ */
+static SDL_bool loaded_xinput = SDL_FALSE;
+
+
+int
+SDL_XINPUT_HapticInit(void)
+{
+ const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
+ if (!env || SDL_atoi(env)) {
+ loaded_xinput = (WIN_LoadXInputDLL() == 0);
+ }
+
+ if (loaded_xinput) {
+ DWORD i;
+ for (i = 0; i < XUSER_MAX_COUNT; i++) {
+ SDL_XINPUT_MaybeAddDevice(i);
+ }
+ }
+ return 0;
+}
+
+int
+SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
+{
+ const Uint8 userid = (Uint8)dwUserid;
+ SDL_hapticlist_item *item;
+ XINPUT_VIBRATION state;
+
+ if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
+ return -1;
+ }
+
+ /* Make sure we don't already have it */
+ for (item = SDL_hapticlist; item; item = item->next) {
+ if (item->bXInputHaptic && item->userid == userid) {
+ return -1; /* Already added */
+ }
+ }
+
+ SDL_zero(state);
+ if (XINPUTSETSTATE(dwUserid, &state) != ERROR_SUCCESS) {
+ return -1; /* no force feedback on this device. */
+ }
+
+ item = (SDL_hapticlist_item *)SDL_malloc(sizeof(SDL_hapticlist_item));
+ if (item == NULL) {
+ return SDL_OutOfMemory();
+ }
+
+ SDL_zerop(item);
+
+ /* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */
+ {
+ char buf[64];
+ SDL_snprintf(buf, sizeof(buf), "XInput Controller #%u", (unsigned int)(userid + 1));
+ item->name = SDL_strdup(buf);
+ }
+
+ if (!item->name) {
+ SDL_free(item);
+ return -1;
+ }
+
+ /* Copy the instance over, useful for creating devices. */
+ item->bXInputHaptic = SDL_TRUE;
+ item->userid = userid;
+
+ return SDL_SYS_AddHapticDevice(item);
+}
+
+int
+SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
+{
+ const Uint8 userid = (Uint8)dwUserid;
+ SDL_hapticlist_item *item;
+ SDL_hapticlist_item *prev = NULL;
+
+ if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
+ return -1;
+ }
+
+ for (item = SDL_hapticlist; item != NULL; item = item->next) {
+ if (item->bXInputHaptic && item->userid == userid) {
+ /* found it, remove it. */
+ return SDL_SYS_RemoveHapticDevice(prev, item);
+ }
+ prev = item;
+ }
+ return -1;
+}
+
+/* !!! FIXME: this is a hack, remove this later. */
+/* Since XInput doesn't offer a way to vibrate for X time, we hook into
+ * SDL_PumpEvents() to check if it's time to stop vibrating with some
+ * frequency.
+ * In practice, this works for 99% of use cases. But in an ideal world,
+ * we do this in a separate thread so that:
+ * - we aren't bound to when the app chooses to pump the event queue.
+ * - we aren't adding more polling to the event queue
+ * - we can emulate all the haptic effects correctly (start on a delay,
+ * mix multiple effects, etc).
+ *
+ * Mostly, this is here to get rumbling to work, and all the other features
+ * are absent in the XInput path for now. :(
+ */
+static int SDLCALL
+SDL_RunXInputHaptic(void *arg)
+{
+ struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;
+
+ while (!hwdata->stopThread) {
+ SDL_Delay(50);
+ SDL_LockMutex(hwdata->mutex);
+ /* If we're currently running and need to stop... */
+ if (hwdata->stopTicks) {
+ if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_TICKS_PASSED(SDL_GetTicks(), hwdata->stopTicks)) {
+ XINPUT_VIBRATION vibration = { 0, 0 };
+ hwdata->stopTicks = 0;
+ XINPUTSETSTATE(hwdata->userid, &vibration);
+ }
+ }
+ SDL_UnlockMutex(hwdata->mutex);
+ }
+
+ return 0;
+}
+
+static int
+SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 userid)
+{
+ char threadName[32];
+ XINPUT_VIBRATION vibration = { 0, 0 }; /* stop any current vibration */
+ XINPUTSETSTATE(userid, &vibration);
+
+ haptic->supported = SDL_HAPTIC_LEFTRIGHT;
+
+ haptic->neffects = 1;
+ haptic->nplaying = 1;
+
+ /* Prepare effects memory. */
+ haptic->effects = (struct haptic_effect *)
+ SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
+ if (haptic->effects == NULL) {
+ return SDL_OutOfMemory();
+ }
+ /* Clear the memory */
+ SDL_memset(haptic->effects, 0,
+ sizeof(struct haptic_effect) * haptic->neffects);
+
+ haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata));
+ if (haptic->hwdata == NULL) {
+ SDL_free(haptic->effects);
+ haptic->effects = NULL;
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
+
+ haptic->hwdata->bXInputHaptic = 1;
+ haptic->hwdata->userid = userid;
+
+ haptic->hwdata->mutex = SDL_CreateMutex();
+ if (haptic->hwdata->mutex == NULL) {
+ SDL_free(haptic->effects);
+ SDL_free(haptic->hwdata);
+ haptic->effects = NULL;
+ return SDL_SetError("Couldn't create XInput haptic mutex");
+ }
+
+ SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%d", (int)userid);
+
+#if defined(__WIN32__) && !defined(HAVE_LIBC) /* !!! FIXME: this is nasty. */
+#undef SDL_CreateThread
+#if SDL_DYNAMIC_API
+ haptic->hwdata->thread = SDL_CreateThread_REAL(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
+#else
+ haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
+#endif
+#else
+ haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata);
+#endif
+ if (haptic->hwdata->thread == NULL) {
+ SDL_DestroyMutex(haptic->hwdata->mutex);
+ SDL_free(haptic->effects);
+ SDL_free(haptic->hwdata);
+ haptic->effects = NULL;
+ return SDL_SetError("Couldn't create XInput haptic thread");
+ }
+
+ return 0;
+}
+
+int
+SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
+{
+ return SDL_XINPUT_HapticOpenFromUserIndex(haptic, item->userid);
+}
+
+int
+SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ return (haptic->hwdata->userid == joystick->hwdata->userid);
+}
+
+int
+SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ SDL_hapticlist_item *item;
+ int index = 0;
+
+ /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
+ for (item = SDL_hapticlist; item != NULL; item = item->next) {
+ if (item->bXInputHaptic && item->userid == joystick->hwdata->userid) {
+ haptic->index = index;
+ return SDL_XINPUT_HapticOpenFromUserIndex(haptic, joystick->hwdata->userid);
+ }
+ ++index;
+ }
+
+ SDL_SetError("Couldn't find joystick in haptic device list");
+ return -1;
+}
+
+void
+SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
+{
+ haptic->hwdata->stopThread = 1;
+ SDL_WaitThread(haptic->hwdata->thread, NULL);
+ SDL_DestroyMutex(haptic->hwdata->mutex);
+}
+
+void
+SDL_XINPUT_HapticQuit(void)
+{
+ if (loaded_xinput) {
+ WIN_UnloadXInputDLL();
+ loaded_xinput = SDL_FALSE;
+ }
+}
+
+int
+SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
+{
+ SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
+ return SDL_XINPUT_HapticUpdateEffect(haptic, effect, base);
+}
+
+int
+SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
+{
+ XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
+ SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT);
+ vib->wLeftMotorSpeed = data->leftright.large_magnitude;
+ vib->wRightMotorSpeed = data->leftright.small_magnitude;
+ SDL_LockMutex(haptic->hwdata->mutex);
+ if (haptic->hwdata->stopTicks) { /* running right now? Update it. */
+ XINPUTSETSTATE(haptic->hwdata->userid, vib);
+ }
+ SDL_UnlockMutex(haptic->hwdata->mutex);
+ return 0;
+}
+
+int
+SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
+{
+ XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
+ SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
+ SDL_LockMutex(haptic->hwdata->mutex);
+ if (effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY) {
+ haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY;
+ } else if ((!effect->effect.leftright.length) || (!iterations)) {
+ /* do nothing. Effect runs for zero milliseconds. */
+ } else {
+ haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
+ if ((haptic->hwdata->stopTicks == SDL_HAPTIC_INFINITY) || (haptic->hwdata->stopTicks == 0)) {
+ haptic->hwdata->stopTicks = 1; /* fix edge cases. */
+ }
+ }
+ SDL_UnlockMutex(haptic->hwdata->mutex);
+ return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
+}
+
+int
+SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ XINPUT_VIBRATION vibration = { 0, 0 };
+ SDL_LockMutex(haptic->hwdata->mutex);
+ haptic->hwdata->stopTicks = 0;
+ SDL_UnlockMutex(haptic->hwdata->mutex);
+ return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
+}
+
+void
+SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ SDL_XINPUT_HapticStopEffect(haptic, effect);
+}
+
+int
+SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticPause(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic)
+{
+ XINPUT_VIBRATION vibration = { 0, 0 };
+ SDL_LockMutex(haptic->hwdata->mutex);
+ haptic->hwdata->stopTicks = 0;
+ SDL_UnlockMutex(haptic->hwdata->mutex);
+ return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
+}
+
+#else /* !SDL_HAPTIC_XINPUT */
+
+
+int
+SDL_XINPUT_HapticInit(void)
+{
+ return 0;
+}
+
+int
+SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+ return SDL_Unsupported();
+}
+
+void
+SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
+{
+}
+
+void
+SDL_XINPUT_HapticQuit(void)
+{
+}
+
+int
+SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ return SDL_Unsupported();
+}
+
+void
+SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+}
+
+int
+SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticPause(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic)
+{
+ return SDL_Unsupported();
+}
+
+#endif /* SDL_HAPTIC_XINPUT */
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/haptic/windows/SDL_xinputhaptic_c.h b/src/haptic/windows/SDL_xinputhaptic_c.h
new file mode 100644
index 000000000..c3062b6ea
--- /dev/null
+++ b/src/haptic/windows/SDL_xinputhaptic_c.h
@@ -0,0 +1,47 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_haptic.h"
+#include "SDL_windowshaptic_c.h"
+
+
+extern int SDL_XINPUT_HapticInit(void);
+extern int SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid);
+extern int SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid);
+extern int SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
+extern int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern void SDL_XINPUT_HapticClose(SDL_Haptic * haptic);
+extern void SDL_XINPUT_HapticQuit(void);
+extern int SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base);
+extern int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data);
+extern int SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations);
+extern int SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain);
+extern int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter);
+extern int SDL_XINPUT_HapticPause(SDL_Haptic * haptic);
+extern int SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic);
+extern int SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic);
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
index 950cb3601..d53acdfb9 100644
--- a/src/joystick/SDL_gamecontroller.c
+++ b/src/joystick/SDL_gamecontroller.c
@@ -88,9 +88,7 @@ typedef struct _ControllerMapping_t
} ControllerMapping_t;
static ControllerMapping_t *s_pSupportedControllers = NULL;
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
static ControllerMapping_t *s_pXInputMapping = NULL;
-#endif
/* The SDL game controller structure */
struct _SDL_GameController
@@ -260,12 +258,10 @@ ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickGUID *gu
*/
ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
{
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
if (SDL_SYS_IsXInputGamepad_DeviceIndex(device_index) && s_pXInputMapping) {
return s_pXInputMapping;
}
else
-#endif
{
SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
return SDL_PrivateGetControllerMappingForGUID(&jGUID);
@@ -669,19 +665,15 @@ SDL_GameControllerAddMapping(const char *mappingString)
char *pchMapping;
SDL_JoystickGUID jGUID;
ControllerMapping_t *pControllerMapping;
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
SDL_bool is_xinput_mapping = SDL_FALSE;
-#endif
pchGUID = SDL_PrivateGetControllerGUIDFromMappingString(mappingString);
if (!pchGUID) {
return SDL_SetError("Couldn't parse GUID from %s", mappingString);
}
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
if (!SDL_strcasecmp(pchGUID, "xinput")) {
is_xinput_mapping = SDL_TRUE;
}
-#endif
jGUID = SDL_JoystickGetGUIDFromString(pchGUID);
SDL_free(pchGUID);
@@ -714,11 +706,9 @@ SDL_GameControllerAddMapping(const char *mappingString)
SDL_free(pchMapping);
return SDL_OutOfMemory();
}
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
if (is_xinput_mapping) {
s_pXInputMapping = pControllerMapping;
}
-#endif
pControllerMapping->guid = jGUID;
pControllerMapping->name = pchName;
pControllerMapping->mapping = pchMapping;
diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h
index 161594f92..89837176c 100644
--- a/src/joystick/SDL_gamecontrollerdb.h
+++ b/src/joystick/SDL_gamecontrollerdb.h
@@ -31,7 +31,10 @@
*/
static const char *s_ControllerMappings [] =
{
-#ifdef SDL_JOYSTICK_DINPUT
+#if SDL_JOYSTICK_XINPUT
+ "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+#endif
+#if SDL_JOYSTICK_DINPUT
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
@@ -41,10 +44,8 @@ static const char *s_ControllerMappings [] =
"4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
"4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
- "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
-#elif defined(SDL_JOYSTICK_XINPUT)
- "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
-#elif defined(__MACOSX__)
+#endif
+#if defined(__MACOSX__)
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
@@ -53,7 +54,8 @@ static const char *s_ControllerMappings [] =
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
-#elif defined(__LINUX__)
+#endif
+#if defined(__LINUX__)
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
@@ -70,7 +72,8 @@ static const char *s_ControllerMappings [] =
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
-#elif defined(__ANDROID__)
+#endif
+#if defined(__ANDROID__)
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
#endif
NULL
diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h
index d5ef3a529..84efe69aa 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -20,6 +20,9 @@
*/
#include "../SDL_internal.h"
+#ifndef _SDL_sysjoystick_h
+#define _SDL_sysjoystick_h
+
/* This is the system specific header for the SDL joystick API */
#include "SDL_joystick.h"
@@ -105,9 +108,9 @@ extern SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index);
/* Function to return the stable GUID for a opened joystick */
extern SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick);
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
/* Function returns SDL_TRUE if this device is an XInput gamepad */
-extern SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex( int device_index );
-#endif
+extern SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index);
+
+#endif /* _SDL_sysjoystick_h */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c
new file mode 100644
index 000000000..c5816e997
--- /dev/null
+++ b/src/joystick/windows/SDL_dinputjoystick.c
@@ -0,0 +1,900 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "../SDL_sysjoystick.h"
+#include "SDL_windowsjoystick_c.h"
+#include "SDL_dinputjoystick_c.h"
+#include "SDL_xinputjoystick_c.h"
+
+
+#if SDL_JOYSTICK_DINPUT
+
+#ifndef DIDFT_OPTIONAL
+#define DIDFT_OPTIONAL 0x80000000
+#endif
+
+#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
+#define AXIS_MIN -32768 /* minimum value for axis coordinate */
+#define AXIS_MAX 32767 /* maximum value for axis coordinate */
+#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
+
+/* external variables referenced. */
+extern HWND SDL_HelperWindow;
+
+/* local variables */
+static SDL_bool coinitialized = SDL_FALSE;
+static LPDIRECTINPUT8 dinput = NULL;
+static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
+static UINT SDL_RawDevListCount = 0;
+
+/* Taken from Wine - Thanks! */
+static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
+ { &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(0), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(1), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(2), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(3), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(4), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(5), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(6), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(7), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(8), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(9), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(10), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(11), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(12), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(13), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(14), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(15), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(16), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(17), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(18), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(19), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(20), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(21), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(22), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(23), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(24), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(25), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(26), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(27), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(28), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(29), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(30), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(31), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(32), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(33), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(34), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(35), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(36), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(37), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(38), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(39), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(40), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(41), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(42), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(43), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(44), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(45), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(46), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(47), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(48), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(49), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(50), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(51), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(52), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(53), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(54), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(55), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(56), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(57), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(58), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(59), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(60), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(61), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(62), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(63), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(64), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(65), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(66), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(67), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(68), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(69), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(70), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(71), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(72), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(73), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(74), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(75), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(76), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(77), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(78), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(79), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(80), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(81), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(82), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(83), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(84), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(85), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(86), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(87), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(88), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(89), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(90), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(91), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(92), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(93), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(94), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(95), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(96), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(97), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(98), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(99), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(100), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(101), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(102), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(103), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(104), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(105), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(106), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(107), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(108), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(109), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(110), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(111), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(112), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(113), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(114), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(115), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(116), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(117), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(118), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(119), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(120), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(121), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(122), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(123), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(124), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(125), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(126), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { NULL, DIJOFS_BUTTON(127), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+ { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+};
+
+const DIDATAFORMAT c_dfDIJoystick2 = {
+ sizeof(DIDATAFORMAT),
+ sizeof(DIOBJECTDATAFORMAT),
+ DIDF_ABSAXIS,
+ sizeof(DIJOYSTATE2),
+ SDL_arraysize(dfDIJoystick2),
+ dfDIJoystick2
+};
+
+/* Convert a DirectInput return code to a text message */
+static int
+SetDIerror(const char *function, HRESULT code)
+{
+ /*
+ return SDL_SetError("%s() [%s]: %s", function,
+ DXGetErrorString9A(code), DXGetErrorDescription9A(code));
+ */
+ return SDL_SetError("%s() DirectX error %d", function, code);
+}
+
+static SDL_bool
+SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
+{
+ static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+
+ static const GUID *s_XInputProductGUID[] = {
+ &IID_ValveStreamingGamepad,
+ &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
+ &IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
+ };
+
+ size_t iDevice;
+ UINT i;
+
+ if (!SDL_XINPUT_Enabled()) {
+ return SDL_FALSE;
+ }
+
+ /* Check for well known XInput device GUIDs */
+ /* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
+ for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
+ if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
+ return SDL_TRUE;
+ }
+ }
+
+ /* Go through RAWINPUT (WinXP and later) to find HID devices. */
+ /* Cache this if we end up using it. */
+ if (SDL_RawDevList == NULL) {
+ if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
+ return SDL_FALSE; /* oh well. */
+ }
+
+ SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
+ if (SDL_RawDevList == NULL) {
+ SDL_OutOfMemory();
+ return SDL_FALSE;
+ }
+
+ if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
+ SDL_free(SDL_RawDevList);
+ SDL_RawDevList = NULL;
+ return SDL_FALSE; /* oh well. */
+ }
+ }
+
+ for (i = 0; i < SDL_RawDevListCount; i++) {
+ RID_DEVICE_INFO rdi;
+ char devName[128];
+ UINT rdiSize = sizeof(rdi);
+ UINT nameSize = SDL_arraysize(devName);
+
+ rdi.cbSize = sizeof(rdi);
+ if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
+ (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
+ (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
+ (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
+ (SDL_strstr(devName, "IG_") != NULL)) {
+ return SDL_TRUE;
+ }
+ }
+
+ return SDL_FALSE;
+}
+
+int
+SDL_DINPUT_JoystickInit(void)
+{
+ HRESULT result;
+ HINSTANCE instance;
+
+ result = WIN_CoInitialize();
+ if (FAILED(result)) {
+ return SetDIerror("CoInitialize", result);
+ }
+
+ coinitialized = SDL_TRUE;
+
+ result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IDirectInput8, (LPVOID)&dinput);
+
+ if (FAILED(result)) {
+ return SetDIerror("CoCreateInstance", result);
+ }
+
+ /* Because we used CoCreateInstance, we need to Initialize it, first. */
+ instance = GetModuleHandle(NULL);
+ if (instance == NULL) {
+ return SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError());
+ }
+ result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
+
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInput::Initialize", result);
+ }
+ return 0;
+}
+
+/* helper function for direct input, gets called for each connected joystick */
+static BOOL CALLBACK
+EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
+{
+ JoyStick_DeviceData *pNewJoystick;
+ JoyStick_DeviceData *pPrevJoystick = NULL;
+
+ if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
+ return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
+ }
+
+ pNewJoystick = *(JoyStick_DeviceData **)pContext;
+ while (pNewJoystick) {
+ if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) {
+ /* if we are replacing the front of the list then update it */
+ if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
+ *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
+ } else if (pPrevJoystick) {
+ pPrevJoystick->pNext = pNewJoystick->pNext;
+ }
+
+ pNewJoystick->pNext = SYS_Joystick;
+ SYS_Joystick = pNewJoystick;
+
+ return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
+ }
+
+ pPrevJoystick = pNewJoystick;
+ pNewJoystick = pNewJoystick->pNext;
+ }
+
+ pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
+ if (!pNewJoystick) {
+ return DIENUM_CONTINUE; /* better luck next time? */
+ }
+
+ SDL_zerop(pNewJoystick);
+ pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
+ if (!pNewJoystick->joystickname) {
+ SDL_free(pNewJoystick);
+ return DIENUM_CONTINUE; /* better luck next time? */
+ }
+
+ SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
+ sizeof(DIDEVICEINSTANCE));
+
+ SDL_memcpy(&pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid));
+ SDL_SYS_AddJoystickDevice(pNewJoystick);
+
+ return DIENUM_CONTINUE; /* get next device, please */
+}
+
+void
+SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
+{
+ IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
+
+ if (SDL_RawDevList) {
+ SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */
+ SDL_RawDevList = NULL;
+ }
+ SDL_RawDevListCount = 0;
+}
+
+static BOOL CALLBACK
+EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
+{
+ SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
+ HRESULT result;
+ input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
+
+ if (dev->dwType & DIDFT_BUTTON) {
+ in->type = BUTTON;
+ in->num = joystick->nbuttons;
+ in->ofs = DIJOFS_BUTTON(in->num);
+ joystick->nbuttons++;
+ } else if (dev->dwType & DIDFT_POV) {
+ in->type = HAT;
+ in->num = joystick->nhats;
+ in->ofs = DIJOFS_POV(in->num);
+ joystick->nhats++;
+ } else if (dev->dwType & DIDFT_AXIS) {
+ DIPROPRANGE diprg;
+ DIPROPDWORD dilong;
+
+ in->type = AXIS;
+ in->num = joystick->naxes;
+ if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
+ in->ofs = DIJOFS_X;
+ else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
+ in->ofs = DIJOFS_Y;
+ else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
+ in->ofs = DIJOFS_Z;
+ else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
+ in->ofs = DIJOFS_RX;
+ else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
+ in->ofs = DIJOFS_RY;
+ else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
+ in->ofs = DIJOFS_RZ;
+ else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
+ in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
+ ++joystick->hwdata->NumSliders;
+ } else {
+ return DIENUM_CONTINUE; /* not an axis we can grok */
+ }
+
+ diprg.diph.dwSize = sizeof(diprg);
+ diprg.diph.dwHeaderSize = sizeof(diprg.diph);
+ diprg.diph.dwObj = dev->dwType;
+ diprg.diph.dwHow = DIPH_BYID;
+ diprg.lMin = AXIS_MIN;
+ diprg.lMax = AXIS_MAX;
+
+ result =
+ IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+ DIPROP_RANGE, &diprg.diph);
+ if (FAILED(result)) {
+ return DIENUM_CONTINUE; /* don't use this axis */
+ }
+
+ /* Set dead zone to 0. */
+ dilong.diph.dwSize = sizeof(dilong);
+ dilong.diph.dwHeaderSize = sizeof(dilong.diph);
+ dilong.diph.dwObj = dev->dwType;
+ dilong.diph.dwHow = DIPH_BYID;
+ dilong.dwData = 0;
+ result =
+ IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+ DIPROP_DEADZONE, &dilong.diph);
+ if (FAILED(result)) {
+ return DIENUM_CONTINUE; /* don't use this axis */
+ }
+
+ joystick->naxes++;
+ } else {
+ /* not supported at this time */
+ return DIENUM_CONTINUE;
+ }
+
+ joystick->hwdata->NumInputs++;
+
+ if (joystick->hwdata->NumInputs == MAX_INPUTS) {
+ return DIENUM_STOP; /* too many */
+ }
+
+ return DIENUM_CONTINUE;
+}
+
+/* Sort using the data offset into the DInput struct.
+ * This gives a reasonable ordering for the inputs.
+ */
+static int
+SortDevFunc(const void *a, const void *b)
+{
+ const input_t *inputA = (const input_t*)a;
+ const input_t *inputB = (const input_t*)b;
+
+ if (inputA->ofs < inputB->ofs)
+ return -1;
+ if (inputA->ofs > inputB->ofs)
+ return 1;
+ return 0;
+}
+
+/* Sort the input objects and recalculate the indices for each input. */
+static void
+SortDevObjects(SDL_Joystick *joystick)
+{
+ input_t *inputs = joystick->hwdata->Inputs;
+ int nButtons = 0;
+ int nHats = 0;
+ int nAxis = 0;
+ int n;
+
+ SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
+
+ for (n = 0; n < joystick->hwdata->NumInputs; n++) {
+ switch (inputs[n].type) {
+ case BUTTON:
+ inputs[n].num = nButtons;
+ nButtons++;
+ break;
+
+ case HAT:
+ inputs[n].num = nHats;
+ nHats++;
+ break;
+
+ case AXIS:
+ inputs[n].num = nAxis;
+ nAxis++;
+ break;
+ }
+ }
+}
+
+int
+SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
+{
+ HRESULT result;
+ LPDIRECTINPUTDEVICE8 device;
+ DIPROPDWORD dipdw;
+
+ joystick->hwdata->buffered = SDL_TRUE;
+ joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
+
+ SDL_zero(dipdw);
+ dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+ dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+
+ result =
+ IDirectInput8_CreateDevice(dinput,
+ &(joystickdevice->dxdevice.guidInstance), &device, NULL);
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInput::CreateDevice", result);
+ }
+
+ /* Now get the IDirectInputDevice8 interface, instead. */
+ result = IDirectInputDevice8_QueryInterface(device,
+ &IID_IDirectInputDevice8,
+ (LPVOID *)& joystick->
+ hwdata->InputDevice);
+ /* We are done with this object. Use the stored one from now on. */
+ IDirectInputDevice8_Release(device);
+
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::QueryInterface", result);
+ }
+
+ /* Acquire shared access. Exclusive access is required for forces,
+ * though. */
+ result =
+ IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
+ InputDevice, SDL_HelperWindow,
+ DISCL_EXCLUSIVE |
+ DISCL_BACKGROUND);
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
+ }
+
+ /* Use the extended data structure: DIJOYSTATE2. */
+ result =
+ IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
+ &c_dfDIJoystick2);
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
+ }
+
+ /* Get device capabilities */
+ result =
+ IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
+ &joystick->hwdata->Capabilities);
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
+ }
+
+ /* Force capable? */
+ if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
+
+ result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::Acquire", result);
+ }
+
+ /* reset all actuators. */
+ result =
+ IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
+ InputDevice,
+ DISFFC_RESET);
+
+ /* Not necessarily supported, ignore if not supported.
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
+ }
+ */
+
+ result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
+
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::Unacquire", result);
+ }
+
+ /* Turn on auto-centering for a ForceFeedback device (until told
+ * otherwise). */
+ dipdw.diph.dwObj = 0;
+ dipdw.diph.dwHow = DIPH_DEVICE;
+ dipdw.dwData = DIPROPAUTOCENTER_ON;
+
+ result =
+ IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+ DIPROP_AUTOCENTER, &dipdw.diph);
+
+ /* Not necessarily supported, ignore if not supported.
+ if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::SetProperty", result);
+ }
+ */
+ }
+
+ /* What buttons and axes does it have? */
+ IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
+ EnumDevObjectsCallback, joystick,
+ DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
+
+ /* Reorder the input objects. Some devices do not report the X axis as
+ * the first axis, for example. */
+ SortDevObjects(joystick);
+
+ dipdw.diph.dwObj = 0;
+ dipdw.diph.dwHow = DIPH_DEVICE;
+ dipdw.dwData = INPUT_QSIZE;
+
+ /* Set the buffer size */
+ result =
+ IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+ DIPROP_BUFFERSIZE, &dipdw.diph);
+
+ if (result == DI_POLLEDDEVICE) {
+ /* This device doesn't support buffering, so we're forced
+ * to use less reliable polling. */
+ joystick->hwdata->buffered = SDL_FALSE;
+ } else if (FAILED(result)) {
+ return SetDIerror("IDirectInputDevice8::SetProperty", result);
+ }
+ return 0;
+}
+
+static Uint8
+TranslatePOV(DWORD value)
+{
+ const int HAT_VALS[] = {
+ SDL_HAT_UP,
+ SDL_HAT_UP | SDL_HAT_RIGHT,
+ SDL_HAT_RIGHT,
+ SDL_HAT_DOWN | SDL_HAT_RIGHT,
+ SDL_HAT_DOWN,
+ SDL_HAT_DOWN | SDL_HAT_LEFT,
+ SDL_HAT_LEFT,
+ SDL_HAT_UP | SDL_HAT_LEFT
+ };
+
+ if (LOWORD(value) == 0xFFFF)
+ return SDL_HAT_CENTERED;
+
+ /* Round the value up: */
+ value += 4500 / 2;
+ value %= 36000;
+ value /= 4500;
+
+ if (value >= 8)
+ return SDL_HAT_CENTERED; /* shouldn't happen */
+
+ return HAT_VALS[value];
+}
+
+static void
+UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
+{
+ int i;
+ HRESULT result;
+ DWORD numevents;
+ DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
+
+ numevents = INPUT_QSIZE;
+ result =
+ IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
+ sizeof(DIDEVICEOBJECTDATA), evtbuf,
+ &numevents, 0);
+ if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
+ IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+ result =
+ IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
+ sizeof(DIDEVICEOBJECTDATA),
+ evtbuf, &numevents, 0);
+ }
+
+ /* Handle the events or punt */
+ if (FAILED(result)) {
+ joystick->hwdata->send_remove_event = SDL_TRUE;
+ joystick->hwdata->removed = SDL_TRUE;
+ return;
+ }
+
+ for (i = 0; i < (int)numevents; ++i) {
+ int j;
+
+ for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
+ const input_t *in = &joystick->hwdata->Inputs[j];
+
+ if (evtbuf[i].dwOfs != in->ofs)
+ continue;
+
+ switch (in->type) {
+ case AXIS:
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
+ break;
+ case BUTTON:
+ SDL_PrivateJoystickButton(joystick, in->num,
+ (Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
+ break;
+ case HAT:
+ {
+ Uint8 pos = TranslatePOV(evtbuf[i].dwData);
+ SDL_PrivateJoystickHat(joystick, in->num, pos);
+ }
+ break;
+ }
+ }
+ }
+}
+
+/* Function to update the state of a joystick - called as a device poll.
+ * This function shouldn't update the joystick structure directly,
+ * but instead should call SDL_PrivateJoystick*() to deliver events
+ * and update joystick device state.
+ */
+static void
+UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
+{
+ DIJOYSTATE2 state;
+ HRESULT result;
+ int i;
+
+ result =
+ IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
+ sizeof(DIJOYSTATE2), &state);
+ if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
+ IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+ result =
+ IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
+ sizeof(DIJOYSTATE2), &state);
+ }
+
+ if (result != DI_OK) {
+ joystick->hwdata->send_remove_event = SDL_TRUE;
+ joystick->hwdata->removed = SDL_TRUE;
+ return;
+ }
+
+ /* Set each known axis, button and POV. */
+ for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
+ const input_t *in = &joystick->hwdata->Inputs[i];
+
+ switch (in->type) {
+ case AXIS:
+ switch (in->ofs) {
+ case DIJOFS_X:
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
+ break;
+ case DIJOFS_Y:
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
+ break;
+ case DIJOFS_Z:
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
+ break;
+ case DIJOFS_RX:
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
+ break;
+ case DIJOFS_RY:
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
+ break;
+ case DIJOFS_RZ:
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
+ break;
+ case DIJOFS_SLIDER(0):
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
+ break;
+ case DIJOFS_SLIDER(1):
+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
+ break;
+ }
+ break;
+
+ case BUTTON:
+ SDL_PrivateJoystickButton(joystick, in->num,
+ (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
+ break;
+ case HAT:
+ {
+ Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
+ SDL_PrivateJoystickHat(joystick, in->num, pos);
+ break;
+ }
+ }
+ }
+}
+
+void
+SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
+{
+ HRESULT result;
+
+ result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
+ if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
+ IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+ IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
+ }
+
+ if (joystick->hwdata->buffered) {
+ UpdateDINPUTJoystickState_Buffered(joystick);
+ } else {
+ UpdateDINPUTJoystickState_Polled(joystick);
+ }
+}
+
+void
+SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
+{
+ IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
+ IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
+}
+
+void
+SDL_DINPUT_JoystickQuit(void)
+{
+ if (dinput != NULL) {
+ IDirectInput8_Release(dinput);
+ dinput = NULL;
+ }
+
+ if (coinitialized) {
+ WIN_CoUninitialize();
+ coinitialized = SDL_FALSE;
+ }
+}
+
+#else /* !SDL_JOYSTICK_DINPUT */
+
+
+int
+SDL_DINPUT_JoystickInit(void)
+{
+ return 0;
+}
+
+void
+SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
+{
+}
+
+int
+SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
+{
+ return SDL_Unsupported();
+}
+
+void
+SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
+{
+}
+
+void
+SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
+{
+}
+
+void
+SDL_DINPUT_JoystickQuit(void)
+{
+}
+
+#endif /* SDL_JOYSTICK_DINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/haptic/windows/SDL_syshaptic_c.h b/src/joystick/windows/SDL_dinputjoystick_c.h
similarity index 70%
rename from src/haptic/windows/SDL_syshaptic_c.h
rename to src/joystick/windows/SDL_dinputjoystick_c.h
index 1e0fa190d..3facf0e5d 100644
--- a/src/haptic/windows/SDL_syshaptic_c.h
+++ b/src/joystick/windows/SDL_dinputjoystick_c.h
@@ -18,11 +18,13 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
+#include "../../SDL_internal.h"
-extern int DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance);
-extern int DirectInputHaptic_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance);
-extern int XInputHaptic_MaybeAddDevice(const DWORD dwUserid);
-extern int XInputHaptic_MaybeRemoveDevice(const DWORD dwUserid);
+extern int SDL_DINPUT_JoystickInit(void);
+extern void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
+extern int SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
+extern void SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick);
+extern void SDL_DINPUT_JoystickClose(SDL_Joystick * joystick);
+extern void SDL_DINPUT_JoystickQuit(void);
/* vi: set ts=4 sw=4 expandtab: */
-
diff --git a/src/joystick/windows/SDL_dxjoystick.c b/src/joystick/windows/SDL_dxjoystick.c
deleted file mode 100644
index e8a4f3bec..000000000
--- a/src/joystick/windows/SDL_dxjoystick.c
+++ /dev/null
@@ -1,1661 +0,0 @@
-/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2014 Sam Lantinga
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-*/
-#include "../../SDL_internal.h"
-
-#ifdef SDL_JOYSTICK_DINPUT
-
-/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
- * A. Formiga's WINMM driver.
- *
- * Hats and sliders are completely untested; the app I'm writing this for mostly
- * doesn't use them and I don't own any joysticks with them.
- *
- * We don't bother to use event notification here. It doesn't seem to work
- * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
- * let it return 0 events. */
-
-#include "SDL_error.h"
-#include "SDL_assert.h"
-#include "SDL_events.h"
-#include "SDL_thread.h"
-#include "SDL_timer.h"
-#include "SDL_mutex.h"
-#include "SDL_events.h"
-#include "SDL_hints.h"
-#include "SDL_joystick.h"
-#include "../SDL_sysjoystick.h"
-#if !SDL_EVENTS_DISABLED
-#include "../../events/SDL_events_c.h"
-#endif
-#include "../../core/windows/SDL_windows.h"
-
-#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
-#include "SDL_dxjoystick_c.h"
-
-#if SDL_HAPTIC_DINPUT
-#include "../../haptic/windows/SDL_syshaptic_c.h" /* For haptic hot plugging */
-#endif
-
-#ifndef DIDFT_OPTIONAL
-#define DIDFT_OPTIONAL 0x80000000
-#endif
-
-DEFINE_GUID(GUID_DEVINTERFACE_HID, 0x4D1E55B2L, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
-
-
-#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
-#define AXIS_MIN -32768 /* minimum value for axis coordinate */
-#define AXIS_MAX 32767 /* maximum value for axis coordinate */
-#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
-
-/* external variables referenced. */
-extern HWND SDL_HelperWindow;
-
-
-/* local variables */
-static SDL_bool coinitialized = SDL_FALSE;
-static LPDIRECTINPUT8 dinput = NULL;
-static SDL_bool s_bDeviceAdded = SDL_FALSE;
-static SDL_bool s_bDeviceRemoved = SDL_FALSE;
-static SDL_JoystickID s_nInstanceID = -1;
-static SDL_cond *s_condJoystickThread = NULL;
-static SDL_mutex *s_mutexJoyStickEnum = NULL;
-static SDL_Thread *s_threadJoystick = NULL;
-static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
-static SDL_bool s_bXInputEnabled = SDL_TRUE;
-
-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 redistributable 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);
- }
-}
-
-
-extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
- LPDIRECTINPUT * ppDI,
- LPUNKNOWN punkOuter);
-struct JoyStick_DeviceData_
-{
- SDL_JoystickGUID guid;
- DIDEVICEINSTANCE dxdevice;
- char *joystickname;
- Uint8 send_add_event;
- SDL_JoystickID nInstanceID;
- SDL_bool bXInputDevice;
- BYTE SubType;
- Uint8 XInputUserId;
- struct JoyStick_DeviceData_ *pNext;
-};
-
-typedef struct JoyStick_DeviceData_ JoyStick_DeviceData;
-
-static JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
-
-/* local prototypes */
-static int SetDIerror(const char *function, HRESULT code);
-static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE *
- pdidInstance, VOID * pContext);
-static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev,
- LPVOID pvRef);
-static void SortDevObjects(SDL_Joystick *joystick);
-static Uint8 TranslatePOV(DWORD value);
-
-/* Taken from Wine - Thanks! */
-DIOBJECTDATAFORMAT dfDIJoystick2[] = {
- { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
- { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
- { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
- { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(32),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(33),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(34),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(35),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(36),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(37),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(38),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(39),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(40),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(41),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(42),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(43),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(44),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(45),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(46),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(47),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(48),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(49),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(50),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(51),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(52),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(53),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(54),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(55),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(56),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(57),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(58),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(59),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(60),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(61),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(62),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(63),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(64),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(65),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(66),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(67),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(68),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(69),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(70),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(71),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(72),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(73),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(74),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(75),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(76),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(77),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(78),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(79),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(80),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(81),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(82),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(83),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(84),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(85),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(86),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(87),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(88),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(89),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(90),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(91),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(92),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(93),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(94),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(95),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(96),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(97),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(98),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(99),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(100),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(101),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(102),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(103),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(104),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(105),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(106),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(107),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(108),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(109),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(110),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(111),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(112),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(113),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(114),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(115),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(116),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(117),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(118),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(119),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(120),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(121),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(122),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(123),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(124),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(125),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(126),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { NULL,DIJOFS_BUTTON(127),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
- { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lVX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lVY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lVZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lVRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lVRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lVRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lAX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lAY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lAZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lARx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lARy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lARz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lFX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lFY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lFZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lFRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lFRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lFRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
- { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-};
-
-const DIDATAFORMAT c_dfDIJoystick2 = {
- sizeof(DIDATAFORMAT),
- sizeof(DIOBJECTDATAFORMAT),
- DIDF_ABSAXIS,
- sizeof(DIJOYSTATE2),
- SDL_arraysize(dfDIJoystick2),
- dfDIJoystick2
-};
-
-
-/* Convert a DirectInput return code to a text message */
-static int
-SetDIerror(const char *function, HRESULT code)
-{
- /*
- return SDL_SetError("%s() [%s]: %s", function,
- DXGetErrorString9A(code), DXGetErrorDescription9A(code));
- */
- return SDL_SetError("%s() DirectX error %d", function, code);
-}
-
-
-#define SAFE_RELEASE(p) \
-{ \
- if (p) { \
- (p)->lpVtbl->Release((p)); \
- (p) = 0; \
- } \
-}
-
-DEFINE_GUID(IID_ValveStreamingGamepad, MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
-DEFINE_GUID(IID_X360WiredGamepad, MAKELONG(0x045E, 0x02A1),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
-DEFINE_GUID(IID_X360WirelessGamepad, MAKELONG(0x045E, 0x028E),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
-
-static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
-static UINT SDL_RawDevListCount = 0;
-
-static SDL_bool
-SDL_XInputUseOldJoystickMapping()
-{
- static int s_XInputUseOldJoystickMapping = -1;
- if (s_XInputUseOldJoystickMapping < 0) {
- const char *hint = SDL_GetHint(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING);
- s_XInputUseOldJoystickMapping = (hint && *hint == '1') ? 1 : 0;
- }
- return (s_XInputUseOldJoystickMapping > 0);
-}
-
-static SDL_bool
-SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
-{
- static const GUID *s_XInputProductGUID[] = {
- &IID_ValveStreamingGamepad,
- &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
- &IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
- };
-
- size_t iDevice;
- UINT i;
-
- if (!s_bXInputEnabled) {
- return SDL_FALSE;
- }
-
- /* Check for well known XInput device GUIDs */
- /* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
- for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
- if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
- return SDL_TRUE;
- }
- }
-
- /* Go through RAWINPUT (WinXP and later) to find HID devices. */
- /* Cache this if we end up using it. */
- if (SDL_RawDevList == NULL) {
- if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
- return SDL_FALSE; /* oh well. */
- }
-
- SDL_RawDevList = (PRAWINPUTDEVICELIST) SDL_malloc(sizeof (RAWINPUTDEVICELIST) * SDL_RawDevListCount);
- if (SDL_RawDevList == NULL) {
- SDL_OutOfMemory();
- return SDL_FALSE;
- }
-
- if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) {
- SDL_free(SDL_RawDevList);
- SDL_RawDevList = NULL;
- return SDL_FALSE; /* oh well. */
- }
- }
-
- for (i = 0; i < SDL_RawDevListCount; i++) {
- RID_DEVICE_INFO rdi;
- char devName[128];
- UINT rdiSize = sizeof (rdi);
- UINT nameSize = SDL_arraysize(devName);
-
- rdi.cbSize = sizeof (rdi);
- if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
- (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
- (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
- (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
- (SDL_strstr(devName, "IG_") != NULL)) {
- return SDL_TRUE;
- }
- }
-
- return SDL_FALSE;
-}
-
-
-static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
-
-/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal
- */
-LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- switch (message) {
- case WM_DEVICECHANGE:
- switch (wParam) {
- case DBT_DEVICEARRIVAL:
- if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
- s_bWindowsDeviceChanged = SDL_TRUE;
- }
- break;
- case DBT_DEVICEREMOVECOMPLETE:
- if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
- s_bWindowsDeviceChanged = SDL_TRUE;
- }
- break;
- }
- return 0;
- }
-
- return DefWindowProc (hwnd, message, wParam, lParam);
-}
-
-
-DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
- 0xC0, 0x4F, 0xB9, 0x51, 0xED);
-
-/* Function/thread to scan the system for joysticks.
- */
-static int
-SDL_JoystickThread(void *_data)
-{
- HWND messageWindow = 0;
- HDEVNOTIFY hNotify = 0;
- DEV_BROADCAST_DEVICEINTERFACE dbh;
- SDL_bool bOpenedXInputDevices[SDL_XINPUT_MAX_DEVICES];
- WNDCLASSEX wincl;
-
- SDL_zero(bOpenedXInputDevices);
-
- WIN_CoInitialize();
-
- SDL_memset(&wincl, 0x0, sizeof(wincl));
- wincl.hInstance = GetModuleHandle(NULL);
- wincl.lpszClassName = L"Message";
- wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; /* This function is called by windows */
- wincl.cbSize = sizeof (WNDCLASSEX);
-
- if (!RegisterClassEx (&wincl)) {
- return WIN_SetError("Failed to create register class for joystick autodetect");
- }
-
- messageWindow = (HWND)CreateWindowEx(0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
- if (!messageWindow) {
- return WIN_SetError("Failed to create message window for joystick autodetect");
- }
-
- SDL_zero(dbh);
-
- dbh.dbcc_size = sizeof(dbh);
- dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
- dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
-
- hNotify = RegisterDeviceNotification(messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
- if (!hNotify) {
- return WIN_SetError("Failed to create notify device for joystick autodetect");
- }
-
- SDL_LockMutex(s_mutexJoyStickEnum);
- while (s_bJoystickThreadQuit == SDL_FALSE) {
- MSG messages;
- SDL_bool bXInputChanged = SDL_FALSE;
-
- SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 300);
-
- while (s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE)) {
- if (GetMessage(&messages, messageWindow, 0, 0) != 0) {
- TranslateMessage(&messages);
- DispatchMessage(&messages);
- }
- }
-
- if (s_bXInputEnabled && XINPUTGETCAPABILITIES) {
- /* scan for any change in XInput devices */
- Uint8 userId;
- for (userId = 0; userId < SDL_XINPUT_MAX_DEVICES; userId++) {
- XINPUT_CAPABILITIES capabilities;
- const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
- const SDL_bool available = (result == ERROR_SUCCESS);
- if (bOpenedXInputDevices[userId] != available) {
- bXInputChanged = SDL_TRUE;
- bOpenedXInputDevices[userId] = available;
- }
- }
- }
-
- if (s_bWindowsDeviceChanged || bXInputChanged) {
- SDL_UnlockMutex(s_mutexJoyStickEnum); /* let main thread go while we SDL_Delay(). */
- SDL_Delay(300); /* wait for direct input to find out about this device */
- SDL_LockMutex(s_mutexJoyStickEnum);
-
- s_bDeviceRemoved = SDL_TRUE;
- s_bDeviceAdded = SDL_TRUE;
- s_bWindowsDeviceChanged = SDL_FALSE;
- }
- }
- SDL_UnlockMutex(s_mutexJoyStickEnum);
-
- if (hNotify)
- UnregisterDeviceNotification(hNotify);
-
- if (messageWindow)
- DestroyWindow(messageWindow);
-
- UnregisterClass(wincl.lpszClassName, wincl.hInstance);
- messageWindow = 0;
- WIN_CoUninitialize();
- return 1;
-}
-
-
-/* Function to scan the system for joysticks.
- * This function should set SDL_numjoysticks to the number of available
- * joysticks. Joystick 0 should be the system default joystick.
- * It should return 0, or -1 on an unrecoverable fatal error.
- */
-int
-SDL_SYS_JoystickInit(void)
-{
- HRESULT result;
- HINSTANCE instance;
- const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
- if (env && !SDL_atoi(env)) {
- s_bXInputEnabled = SDL_FALSE;
- }
-
- result = WIN_CoInitialize();
- if (FAILED(result)) {
- return SetDIerror("CoInitialize", result);
- }
-
- coinitialized = SDL_TRUE;
-
- result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
- &IID_IDirectInput8, (LPVOID)&dinput);
-
- if (FAILED(result)) {
- SDL_SYS_JoystickQuit();
- return SetDIerror("CoCreateInstance", result);
- }
-
- /* Because we used CoCreateInstance, we need to Initialize it, first. */
- instance = GetModuleHandle(NULL);
- if (instance == NULL) {
- SDL_SYS_JoystickQuit();
- return SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError());
- }
- result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
-
- if (FAILED(result)) {
- SDL_SYS_JoystickQuit();
- return SetDIerror("IDirectInput::Initialize", result);
- }
-
- if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
- s_bXInputEnabled = SDL_FALSE; /* oh well. */
- }
-
- s_mutexJoyStickEnum = SDL_CreateMutex();
- s_condJoystickThread = SDL_CreateCond();
- s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
-
- SDL_SYS_JoystickDetect();
-
- if (!s_threadJoystick) {
- s_bJoystickThreadQuit = SDL_FALSE;
- /* spin up the thread to detect hotplug of devices */
-#if defined(__WIN32__) && !defined(HAVE_LIBC)
-#undef SDL_CreateThread
-#if SDL_DYNAMIC_API
- s_threadJoystick= SDL_CreateThread_REAL(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
-#else
- s_threadJoystick= SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
-#endif
-#else
- s_threadJoystick = SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL);
-#endif
- }
- return SDL_SYS_NumJoysticks();
-}
-
-/* return the number of joysticks that are connected right now */
-int SDL_SYS_NumJoysticks()
-{
- int nJoysticks = 0;
- JoyStick_DeviceData *device = SYS_Joystick;
- while (device) {
- nJoysticks++;
- device = device->pNext;
- }
-
- return nJoysticks;
-}
-
-/* helper function for direct input, gets called for each connected joystick */
-static BOOL CALLBACK
-EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
-{
- JoyStick_DeviceData *pNewJoystick;
- JoyStick_DeviceData *pPrevJoystick = NULL;
-
- if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
- return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
- }
-
- pNewJoystick = *(JoyStick_DeviceData **)pContext;
- while (pNewJoystick) {
- if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) {
- /* if we are replacing the front of the list then update it */
- if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
- *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
- } else if (pPrevJoystick) {
- pPrevJoystick->pNext = pNewJoystick->pNext;
- }
-
- pNewJoystick->pNext = SYS_Joystick;
- SYS_Joystick = pNewJoystick;
-
- return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
- }
-
- pPrevJoystick = pNewJoystick;
- pNewJoystick = pNewJoystick->pNext;
- }
-
- pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
- if (!pNewJoystick) {
- return DIENUM_CONTINUE; /* better luck next time? */
- }
-
- SDL_zerop(pNewJoystick);
- pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
- if (!pNewJoystick->joystickname) {
- SDL_free(pNewJoystick);
- return DIENUM_CONTINUE; /* better luck next time? */
- }
-
- SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
- sizeof(DIDEVICEINSTANCE));
-
- pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
- pNewJoystick->send_add_event = SDL_TRUE;
- pNewJoystick->nInstanceID = ++s_nInstanceID;
- SDL_memcpy(&pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid));
- pNewJoystick->pNext = SYS_Joystick;
- SYS_Joystick = pNewJoystick;
-
- s_bDeviceAdded = SDL_TRUE;
-
- return DIENUM_CONTINUE; /* get next device, please */
-}
-
-static char *
-GetXInputName(const Uint8 userid, BYTE SubType)
-{
- char name[32];
-
- if (SDL_XInputUseOldJoystickMapping()) {
- SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid);
- } else {
- switch (SubType) {
- case XINPUT_DEVSUBTYPE_GAMEPAD:
- SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid);
- break;
- case XINPUT_DEVSUBTYPE_WHEEL:
- SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid);
- break;
- case XINPUT_DEVSUBTYPE_ARCADE_STICK:
- SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid);
- break;
- case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
- SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid);
- break;
- case XINPUT_DEVSUBTYPE_DANCE_PAD:
- SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + userid);
- break;
- case XINPUT_DEVSUBTYPE_GUITAR:
- case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
- case XINPUT_DEVSUBTYPE_GUITAR_BASS:
- SDL_snprintf(name, sizeof(name), "XInput Guitar #%u", 1 + userid);
- break;
- case XINPUT_DEVSUBTYPE_DRUM_KIT:
- SDL_snprintf(name, sizeof(name), "XInput DrumKit #%u", 1 + userid);
- break;
- case XINPUT_DEVSUBTYPE_ARCADE_PAD:
- SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%u", 1 + userid);
- break;
- default:
- SDL_snprintf(name, sizeof(name), "XInput Device #%u", 1 + userid);
- break;
- }
- }
- return SDL_strdup(name);
-}
-
-static void
-AddXInputDevice(const Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
-{
- JoyStick_DeviceData *pPrevJoystick = NULL;
- JoyStick_DeviceData *pNewJoystick = *pContext;
-
- if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
- return;
-
- if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN)
- return;
-
- while (pNewJoystick) {
- if (pNewJoystick->bXInputDevice && (pNewJoystick->XInputUserId == userid) && (pNewJoystick->SubType == SubType)) {
- /* if we are replacing the front of the list then update it */
- if (pNewJoystick == *pContext) {
- *pContext = pNewJoystick->pNext;
- } else if (pPrevJoystick) {
- pPrevJoystick->pNext = pNewJoystick->pNext;
- }
-
- pNewJoystick->pNext = SYS_Joystick;
- SYS_Joystick = pNewJoystick;
- return; /* already in the list. */
- }
-
- pPrevJoystick = pNewJoystick;
- pNewJoystick = pNewJoystick->pNext;
- }
-
- pNewJoystick = (JoyStick_DeviceData *) SDL_malloc(sizeof (JoyStick_DeviceData));
- if (!pNewJoystick) {
- return; /* better luck next time? */
- }
- SDL_zerop(pNewJoystick);
-
- pNewJoystick->joystickname = GetXInputName(userid,SubType);
- if (!pNewJoystick->joystickname) {
- SDL_free(pNewJoystick);
- return; /* better luck next time? */
- }
-
- pNewJoystick->bXInputDevice = SDL_TRUE;
- if (SDL_XInputUseOldJoystickMapping()) {
- SDL_zero(pNewJoystick->guid);
- } else {
- pNewJoystick->guid.data[0] = 'x';
- pNewJoystick->guid.data[1] = 'i';
- pNewJoystick->guid.data[2] = 'n';
- pNewJoystick->guid.data[3] = 'p';
- pNewJoystick->guid.data[4] = 'u';
- pNewJoystick->guid.data[5] = 't';
- pNewJoystick->guid.data[6] = SubType;
- }
- pNewJoystick->SubType = SubType;
- pNewJoystick->XInputUserId = userid;
- pNewJoystick->send_add_event = SDL_TRUE;
- pNewJoystick->nInstanceID = ++s_nInstanceID;
- pNewJoystick->pNext = SYS_Joystick;
- SYS_Joystick = pNewJoystick;
-
- s_bDeviceAdded = SDL_TRUE;
-}
-
-static void
-EnumXInputDevices(JoyStick_DeviceData **pContext)
-{
- if (s_bXInputEnabled) {
- int iuserid;
- /* iterate in reverse, so these are in the final list in ascending numeric order. */
- for (iuserid = SDL_XINPUT_MAX_DEVICES-1; iuserid >= 0; iuserid--) {
- const Uint8 userid = (Uint8) iuserid;
- XINPUT_CAPABILITIES capabilities;
- if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
- AddXInputDevice(userid, capabilities.SubType, pContext);
- }
- }
- }
-}
-
-
-/* detect any new joysticks being inserted into the system */
-void SDL_SYS_JoystickDetect()
-{
- JoyStick_DeviceData *pCurList = NULL;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
-
- /* only enum the devices if the joystick thread told us something changed */
- if (!s_bDeviceAdded && !s_bDeviceRemoved) {
- return; /* thread hasn't signaled, nothing to do right now. */
- }
-
- SDL_LockMutex(s_mutexJoyStickEnum);
-
- s_bDeviceAdded = SDL_FALSE;
- s_bDeviceRemoved = SDL_FALSE;
-
- pCurList = SYS_Joystick;
- SYS_Joystick = NULL;
-
- /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
- IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, &pCurList, DIEDFL_ATTACHEDONLY);
-
- SDL_free(SDL_RawDevList); /* in case we used this in DirectInput enumerator. */
- SDL_RawDevList = NULL;
- SDL_RawDevListCount = 0;
-
- /* Look for XInput devices. Do this last, so they're first in the final list. */
- EnumXInputDevices(&pCurList);
-
- SDL_UnlockMutex(s_mutexJoyStickEnum);
-
- while (pCurList) {
- JoyStick_DeviceData *pListNext = NULL;
-
-#if SDL_HAPTIC_DINPUT
- if (pCurList->bXInputDevice) {
- XInputHaptic_MaybeRemoveDevice(pCurList->XInputUserId);
- } else {
- DirectInputHaptic_MaybeRemoveDevice(&pCurList->dxdevice);
- }
-#endif
-
-#if !SDL_EVENTS_DISABLED
- SDL_zero(event);
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = pCurList->nInstanceID;
- if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
-
- pListNext = pCurList->pNext;
- SDL_free(pCurList->joystickname);
- SDL_free(pCurList);
- pCurList = pListNext;
- }
-
- if (s_bDeviceAdded) {
- JoyStick_DeviceData *pNewJoystick;
- int device_index = 0;
- s_bDeviceAdded = SDL_FALSE;
- pNewJoystick = SYS_Joystick;
- while (pNewJoystick) {
- if (pNewJoystick->send_add_event) {
-#if SDL_HAPTIC_DINPUT
- if (pNewJoystick->bXInputDevice) {
- XInputHaptic_MaybeAddDevice(pNewJoystick->XInputUserId);
- } else {
- DirectInputHaptic_MaybeAddDevice(&pNewJoystick->dxdevice);
- }
-#endif
-
-#if !SDL_EVENTS_DISABLED
- SDL_zero(event);
- event.type = SDL_JOYDEVICEADDED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = device_index;
- if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
- pNewJoystick->send_add_event = SDL_FALSE;
- }
- device_index++;
- pNewJoystick = pNewJoystick->pNext;
- }
- }
-}
-
-/* Function to get the device-dependent name of a joystick */
-const char *
-SDL_SYS_JoystickNameForDeviceIndex(int device_index)
-{
- JoyStick_DeviceData *device = SYS_Joystick;
-
- for (; device_index > 0; device_index--)
- device = device->pNext;
-
- return device->joystickname;
-}
-
-/* Function to perform the mapping between current device instance and this joysticks instance id */
-SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
-{
- JoyStick_DeviceData *device = SYS_Joystick;
- int index;
-
- for (index = device_index; index > 0; index--)
- device = device->pNext;
-
- return device->nInstanceID;
-}
-
-/* Function to open a joystick for use.
- The joystick to open is specified by the index field of the joystick.
- This should fill the nbuttons and naxes fields of the joystick structure.
- It returns 0, or -1 if there is an error.
- */
-int
-SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
-{
- HRESULT result;
- JoyStick_DeviceData *joystickdevice = SYS_Joystick;
-
- for (; device_index > 0; device_index--)
- joystickdevice = joystickdevice->pNext;
-
- /* allocate memory for system specific hardware data */
- joystick->instance_id = joystickdevice->nInstanceID;
- joystick->closed = SDL_FALSE;
- joystick->hwdata =
- (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
- if (joystick->hwdata == NULL) {
- return SDL_OutOfMemory();
- }
- SDL_zerop(joystick->hwdata);
- joystick->hwdata->guid = joystickdevice->guid;
-
- if (joystickdevice->bXInputDevice) {
- const Uint8 userId = joystickdevice->XInputUserId;
- XINPUT_CAPABILITIES capabilities;
- XINPUT_VIBRATION state;
-
- SDL_assert(s_bXInputEnabled);
- SDL_assert(XINPUTGETCAPABILITIES);
- SDL_assert(XINPUTSETSTATE);
- SDL_assert(userId >= 0);
- SDL_assert(userId < SDL_XINPUT_MAX_DEVICES);
-
- joystick->hwdata->bXInputDevice = SDL_TRUE;
-
- if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
- SDL_free(joystick->hwdata);
- joystick->hwdata = NULL;
- return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
- }
- SDL_zero(state);
- joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS);
- joystick->hwdata->userid = userId;
-
- /* The XInput API has a hard coded button/axis mapping, so we just match it */
- if (SDL_XInputUseOldJoystickMapping()) {
- joystick->naxes = 6;
- joystick->nbuttons = 15;
- } else {
- joystick->naxes = 6;
- joystick->nbuttons = 11;
- joystick->nhats = 1;
- }
- } else { /* use DirectInput, not XInput. */
- LPDIRECTINPUTDEVICE8 device;
- DIPROPDWORD dipdw;
-
- joystick->hwdata->buffered = 1;
- joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
-
- SDL_zero(dipdw);
- dipdw.diph.dwSize = sizeof(DIPROPDWORD);
- dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
-
- result =
- IDirectInput8_CreateDevice(dinput,
- &(joystickdevice->dxdevice.guidInstance), &device, NULL);
- if (FAILED(result)) {
- return SetDIerror("IDirectInput::CreateDevice", result);
- }
-
- /* Now get the IDirectInputDevice8 interface, instead. */
- result = IDirectInputDevice8_QueryInterface(device,
- &IID_IDirectInputDevice8,
- (LPVOID *) & joystick->
- hwdata->InputDevice);
- /* We are done with this object. Use the stored one from now on. */
- IDirectInputDevice8_Release(device);
-
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::QueryInterface", result);
- }
-
- /* Acquire shared access. Exclusive access is required for forces,
- * though. */
- result =
- IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
- InputDevice, SDL_HelperWindow,
- DISCL_EXCLUSIVE |
- DISCL_BACKGROUND);
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
- }
-
- /* Use the extended data structure: DIJOYSTATE2. */
- result =
- IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
- &c_dfDIJoystick2);
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
- }
-
- /* Get device capabilities */
- result =
- IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
- &joystick->hwdata->Capabilities);
-
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
- }
-
- /* Force capable? */
- if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
-
- result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
-
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::Acquire", result);
- }
-
- /* reset all actuators. */
- result =
- IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
- InputDevice,
- DISFFC_RESET);
-
- /* Not necessarily supported, ignore if not supported.
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
- }
- */
-
- result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
-
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::Unacquire", result);
- }
-
- /* Turn on auto-centering for a ForceFeedback device (until told
- * otherwise). */
- dipdw.diph.dwObj = 0;
- dipdw.diph.dwHow = DIPH_DEVICE;
- dipdw.dwData = DIPROPAUTOCENTER_ON;
-
- result =
- IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
- DIPROP_AUTOCENTER, &dipdw.diph);
-
- /* Not necessarily supported, ignore if not supported.
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::SetProperty", result);
- }
- */
- }
-
- /* What buttons and axes does it have? */
- IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
- EnumDevObjectsCallback, joystick,
- DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
-
- /* Reorder the input objects. Some devices do not report the X axis as
- * the first axis, for example. */
- SortDevObjects(joystick);
-
- dipdw.diph.dwObj = 0;
- dipdw.diph.dwHow = DIPH_DEVICE;
- dipdw.dwData = INPUT_QSIZE;
-
- /* Set the buffer size */
- result =
- IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
- DIPROP_BUFFERSIZE, &dipdw.diph);
-
- if (result == DI_POLLEDDEVICE) {
- /* This device doesn't support buffering, so we're forced
- * to use less reliable polling. */
- joystick->hwdata->buffered = 0;
- } else if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::SetProperty", result);
- }
- }
- return (0);
-}
-
-/* return true if this joystick is plugged in right now */
-SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
-{
- return !joystick->closed && !joystick->hwdata->removed;
-}
-
-
-/* Sort using the data offset into the DInput struct.
- * This gives a reasonable ordering for the inputs. */
-static int
-SortDevFunc(const void *a, const void *b)
-{
- const input_t *inputA = (const input_t*)a;
- const input_t *inputB = (const input_t*)b;
-
- if (inputA->ofs < inputB->ofs)
- return -1;
- if (inputA->ofs > inputB->ofs)
- return 1;
- return 0;
-}
-
-/* Sort the input objects and recalculate the indices for each input. */
-static void
-SortDevObjects(SDL_Joystick *joystick)
-{
- input_t *inputs = joystick->hwdata->Inputs;
- int nButtons = 0;
- int nHats = 0;
- int nAxis = 0;
- int n;
-
- SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
-
- for (n = 0; n < joystick->hwdata->NumInputs; n++) {
- switch (inputs[n].type) {
- case BUTTON:
- inputs[n].num = nButtons;
- nButtons++;
- break;
-
- case HAT:
- inputs[n].num = nHats;
- nHats++;
- break;
-
- case AXIS:
- inputs[n].num = nAxis;
- nAxis++;
- break;
- }
- }
-}
-
-static BOOL CALLBACK
-EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
-{
- SDL_Joystick *joystick = (SDL_Joystick *) pvRef;
- HRESULT result;
- input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
-
- if (dev->dwType & DIDFT_BUTTON) {
- in->type = BUTTON;
- in->num = joystick->nbuttons;
- in->ofs = DIJOFS_BUTTON(in->num);
- joystick->nbuttons++;
- } else if (dev->dwType & DIDFT_POV) {
- in->type = HAT;
- in->num = joystick->nhats;
- in->ofs = DIJOFS_POV(in->num);
- joystick->nhats++;
- } else if (dev->dwType & DIDFT_AXIS) {
- DIPROPRANGE diprg;
- DIPROPDWORD dilong;
-
- in->type = AXIS;
- in->num = joystick->naxes;
- if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_X;
- else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_Y;
- else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_Z;
- else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_RX;
- else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_RY;
- else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_RZ;
- else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
- in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
- ++joystick->hwdata->NumSliders;
- } else {
- return DIENUM_CONTINUE; /* not an axis we can grok */
- }
-
- diprg.diph.dwSize = sizeof(diprg);
- diprg.diph.dwHeaderSize = sizeof(diprg.diph);
- diprg.diph.dwObj = dev->dwType;
- diprg.diph.dwHow = DIPH_BYID;
- diprg.lMin = AXIS_MIN;
- diprg.lMax = AXIS_MAX;
-
- result =
- IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
- DIPROP_RANGE, &diprg.diph);
- if (FAILED(result)) {
- return DIENUM_CONTINUE; /* don't use this axis */
- }
-
- /* Set dead zone to 0. */
- dilong.diph.dwSize = sizeof(dilong);
- dilong.diph.dwHeaderSize = sizeof(dilong.diph);
- dilong.diph.dwObj = dev->dwType;
- dilong.diph.dwHow = DIPH_BYID;
- dilong.dwData = 0;
- result =
- IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
- DIPROP_DEADZONE, &dilong.diph);
- if (FAILED(result)) {
- return DIENUM_CONTINUE; /* don't use this axis */
- }
-
- joystick->naxes++;
- } else {
- /* not supported at this time */
- return DIENUM_CONTINUE;
- }
-
- joystick->hwdata->NumInputs++;
-
- if (joystick->hwdata->NumInputs == MAX_INPUTS) {
- return DIENUM_STOP; /* too many */
- }
-
- return DIENUM_CONTINUE;
-}
-
-/* Function to update the state of a joystick - called as a device poll.
- * This function shouldn't update the joystick structure directly,
- * but instead should call SDL_PrivateJoystick*() to deliver events
- * and update joystick device state.
- */
-void
-SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick)
-{
- DIJOYSTATE2 state;
- HRESULT result;
- int i;
-
- result =
- IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
- sizeof(DIJOYSTATE2), &state);
- if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
- IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
- result =
- IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
- sizeof(DIJOYSTATE2), &state);
- }
-
- if (result != DI_OK) {
- joystick->hwdata->send_remove_event = SDL_TRUE;
- joystick->hwdata->removed = SDL_TRUE;
- return;
- }
-
- /* Set each known axis, button and POV. */
- for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
- const input_t *in = &joystick->hwdata->Inputs[i];
-
- switch (in->type) {
- case AXIS:
- switch (in->ofs) {
- case DIJOFS_X:
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lX);
- break;
- case DIJOFS_Y:
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lY);
- break;
- case DIJOFS_Z:
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lZ);
- break;
- case DIJOFS_RX:
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lRx);
- break;
- case DIJOFS_RY:
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lRy);
- break;
- case DIJOFS_RZ:
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lRz);
- break;
- case DIJOFS_SLIDER(0):
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.rglSlider[0]);
- break;
- case DIJOFS_SLIDER(1):
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.rglSlider[1]);
- break;
- }
- break;
-
- case BUTTON:
- SDL_PrivateJoystickButton(joystick, in->num,
- (Uint8) (state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
- break;
- case HAT:
- {
- Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
- SDL_PrivateJoystickHat(joystick, in->num, pos);
- break;
- }
- }
- }
-}
-
-void
-SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
-{
- int i;
- HRESULT result;
- DWORD numevents;
- DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
-
- numevents = INPUT_QSIZE;
- result =
- IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
- sizeof(DIDEVICEOBJECTDATA), evtbuf,
- &numevents, 0);
- if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
- IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
- result =
- IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
- sizeof(DIDEVICEOBJECTDATA),
- evtbuf, &numevents, 0);
- }
-
- /* Handle the events or punt */
- if (FAILED(result)) {
- joystick->hwdata->send_remove_event = SDL_TRUE;
- joystick->hwdata->removed = SDL_TRUE;
- return;
- }
-
- for (i = 0; i < (int) numevents; ++i) {
- int j;
-
- for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
- const input_t *in = &joystick->hwdata->Inputs[j];
-
- if (evtbuf[i].dwOfs != in->ofs)
- continue;
-
- switch (in->type) {
- case AXIS:
- SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) evtbuf[i].dwData);
- break;
- case BUTTON:
- SDL_PrivateJoystickButton(joystick, in->num,
- (Uint8) (evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
- break;
- case HAT:
- {
- Uint8 pos = TranslatePOV(evtbuf[i].dwData);
- SDL_PrivateJoystickHat(joystick, in->num, pos);
- }
- }
- }
- }
-}
-
-static void
-UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
-{
- static WORD s_XInputButtons[] = {
- XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
- XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
- XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER,
- XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
- XINPUT_GAMEPAD_GUIDE
- };
- WORD wButtons = pXInputState->Gamepad.wButtons;
- Uint8 button;
- Uint8 hat = SDL_HAT_CENTERED;
-
- SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
- SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
- SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX);
- SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
- SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
- SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
-
- for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
- SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
- }
-}
-
-static void
-UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
-{
- static WORD s_XInputButtons[] = {
- XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
- XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
- XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
- XINPUT_GAMEPAD_GUIDE
- };
- WORD wButtons = pXInputState->Gamepad.wButtons;
- Uint8 button;
- Uint8 hat = SDL_HAT_CENTERED;
-
- SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
- SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
- SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
- SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX);
- SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
- SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
-
- for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
- SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
- }
-
- if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
- hat |= SDL_HAT_UP;
- }
- if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
- hat |= SDL_HAT_DOWN;
- }
- if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
- hat |= SDL_HAT_LEFT;
- }
- if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
- hat |= SDL_HAT_RIGHT;
- }
- SDL_PrivateJoystickHat(joystick, 0, hat);
-}
-
-/* Function to update the state of a XInput style joystick.
-*/
-void
-SDL_SYS_JoystickUpdate_XInput(SDL_Joystick * joystick)
-{
- HRESULT result;
- XINPUT_STATE_EX XInputState;
-
- if (!XINPUTGETSTATE)
- return;
-
- result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
- if (result == ERROR_DEVICE_NOT_CONNECTED) {
- joystick->hwdata->send_remove_event = SDL_TRUE;
- joystick->hwdata->removed = SDL_TRUE;
- return;
- }
-
- /* only fire events if the data changed from last time */
- if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
- if (SDL_XInputUseOldJoystickMapping()) {
- UpdateXInputJoystickState_OLD(joystick, &XInputState);
- } else {
- UpdateXInputJoystickState(joystick, &XInputState);
- }
- joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
- }
-}
-
-static Uint8
-TranslatePOV(DWORD value)
-{
- const int HAT_VALS[] = {
- SDL_HAT_UP,
- SDL_HAT_UP | SDL_HAT_RIGHT,
- SDL_HAT_RIGHT,
- SDL_HAT_DOWN | SDL_HAT_RIGHT,
- SDL_HAT_DOWN,
- SDL_HAT_DOWN | SDL_HAT_LEFT,
- SDL_HAT_LEFT,
- SDL_HAT_UP | SDL_HAT_LEFT
- };
-
- if (LOWORD(value) == 0xFFFF)
- return SDL_HAT_CENTERED;
-
- /* Round the value up: */
- value += 4500 / 2;
- value %= 36000;
- value /= 4500;
-
- if (value >= 8)
- return SDL_HAT_CENTERED; /* shouldn't happen */
-
- return HAT_VALS[value];
-}
-
-void
-SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
-{
- HRESULT result;
-
- if (joystick->closed || !joystick->hwdata)
- return;
-
- if (joystick->hwdata->bXInputDevice) {
- SDL_SYS_JoystickUpdate_XInput(joystick);
- } else {
- result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
- if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
- IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
- IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
- }
-
- if (joystick->hwdata->buffered)
- SDL_SYS_JoystickUpdate_Buffered(joystick);
- else
- SDL_SYS_JoystickUpdate_Polled(joystick);
- }
-
- if (joystick->hwdata->removed) {
- joystick->closed = SDL_TRUE;
- joystick->uncentered = SDL_TRUE;
- }
-}
-
-/* Function to close a joystick after use */
-void
-SDL_SYS_JoystickClose(SDL_Joystick * joystick)
-{
- if (!joystick->hwdata->bXInputDevice) {
- IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
- IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
- }
-
- /* free system specific hardware data */
- SDL_free(joystick->hwdata);
-
- joystick->closed = SDL_TRUE;
-}
-
-/* Function to perform any system-specific joystick related cleanup */
-void
-SDL_SYS_JoystickQuit(void)
-{
- JoyStick_DeviceData *device = SYS_Joystick;
-
- while (device) {
- JoyStick_DeviceData *device_next = device->pNext;
- SDL_free(device->joystickname);
- SDL_free(device);
- device = device_next;
- }
- SYS_Joystick = NULL;
-
- if (s_threadJoystick) {
- SDL_LockMutex(s_mutexJoyStickEnum);
- s_bJoystickThreadQuit = SDL_TRUE;
- SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
- SDL_UnlockMutex(s_mutexJoyStickEnum);
- SDL_WaitThread(s_threadJoystick, NULL); /* wait for it to bugger off */
-
- SDL_DestroyMutex(s_mutexJoyStickEnum);
- SDL_DestroyCond(s_condJoystickThread);
- s_condJoystickThread= NULL;
- s_mutexJoyStickEnum = NULL;
- s_threadJoystick = NULL;
- }
-
- if (dinput != NULL) {
- IDirectInput8_Release(dinput);
- dinput = NULL;
- }
-
- if (coinitialized) {
- WIN_CoUninitialize();
- coinitialized = SDL_FALSE;
- }
-
- if (s_bXInputEnabled) {
- WIN_UnloadXInputDLL();
- }
-}
-
-/* return the stable device guid for this device index */
-SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
-{
- JoyStick_DeviceData *device = SYS_Joystick;
- int index;
-
- for (index = device_index; index > 0; index--)
- device = device->pNext;
-
- return device->guid;
-}
-
-SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
-{
- return joystick->hwdata->guid;
-}
-
-SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
-{
- JoyStick_DeviceData *device = SYS_Joystick;
- int index;
-
- for (index = device_index; index > 0; index--)
- device = device->pNext;
-
- return (device->SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
-}
-
-#endif /* SDL_JOYSTICK_DINPUT */
-
-/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c
new file mode 100644
index 000000000..9028e3d5c
--- /dev/null
+++ b/src/joystick/windows/SDL_windowsjoystick.c
@@ -0,0 +1,569 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT
+
+/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
+ * A. Formiga's WINMM driver.
+ *
+ * Hats and sliders are completely untested; the app I'm writing this for mostly
+ * doesn't use them and I don't own any joysticks with them.
+ *
+ * We don't bother to use event notification here. It doesn't seem to work
+ * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
+ * let it return 0 events. */
+
+#include "SDL_error.h"
+#include "SDL_assert.h"
+#include "SDL_events.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+#include "SDL_mutex.h"
+#include "SDL_events.h"
+#include "SDL_hints.h"
+#include "SDL_joystick.h"
+#include "../SDL_sysjoystick.h"
+#if !SDL_EVENTS_DISABLED
+#include "../../events/SDL_events_c.h"
+#endif
+#include "../../core/windows/SDL_windows.h"
+#include
+
+#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
+#include "SDL_windowsjoystick_c.h"
+#include "SDL_dinputjoystick_c.h"
+#include "SDL_xinputjoystick_c.h"
+
+#include "../../haptic/windows/SDL_dinputhaptic_c.h" /* For haptic hot plugging */
+#include "../../haptic/windows/SDL_xinputhaptic_c.h" /* For haptic hot plugging */
+
+
+/* local variables */
+static SDL_bool s_bDeviceAdded = SDL_FALSE;
+static SDL_bool s_bDeviceRemoved = SDL_FALSE;
+static SDL_JoystickID s_nInstanceID = -1;
+static SDL_cond *s_condJoystickThread = NULL;
+static SDL_mutex *s_mutexJoyStickEnum = NULL;
+static SDL_Thread *s_threadJoystick = NULL;
+static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
+
+JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
+
+static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
+
+#ifdef __WINRT__
+
+typedef struct
+{
+ int unused;
+} SDL_DeviceNotificationData;
+
+static void
+SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
+{
+}
+
+static int
+SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
+{
+ return 0;
+}
+
+static void
+SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
+{
+}
+
+#else /* !__WINRT__ */
+
+typedef struct
+{
+ HRESULT coinitialized;
+ WNDCLASSEX wincl;
+ HWND messageWindow;
+ HDEVNOTIFY hNotify;
+} SDL_DeviceNotificationData;
+
+
+/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
+static LRESULT CALLBACK
+SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WM_DEVICECHANGE:
+ switch (wParam) {
+ case DBT_DEVICEARRIVAL:
+ if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
+ s_bWindowsDeviceChanged = SDL_TRUE;
+ }
+ break;
+ case DBT_DEVICEREMOVECOMPLETE:
+ if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
+ s_bWindowsDeviceChanged = SDL_TRUE;
+ }
+ break;
+ }
+ return 0;
+ }
+
+ return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+static void
+SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
+{
+ if (data->hNotify)
+ UnregisterDeviceNotification(data->hNotify);
+
+ if (data->messageWindow)
+ DestroyWindow(data->messageWindow);
+
+ UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
+
+ if (data->coinitialized == S_OK) {
+ WIN_CoUninitialize();
+ }
+}
+
+static int
+SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
+{
+ DEV_BROADCAST_DEVICEINTERFACE dbh;
+ GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
+
+ SDL_zerop(data);
+
+ data->coinitialized = WIN_CoInitialize();
+
+ data->wincl.hInstance = GetModuleHandle(NULL);
+ data->wincl.lpszClassName = L"Message";
+ data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; /* This function is called by windows */
+ data->wincl.cbSize = sizeof (WNDCLASSEX);
+
+ if (!RegisterClassEx(&data->wincl)) {
+ WIN_SetError("Failed to create register class for joystick autodetect");
+ SDL_CleanupDeviceNotification(data);
+ return -1;
+ }
+
+ data->messageWindow = (HWND)CreateWindowEx(0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
+ if (!data->messageWindow) {
+ WIN_SetError("Failed to create message window for joystick autodetect");
+ SDL_CleanupDeviceNotification(data);
+ return -1;
+ }
+
+ SDL_zero(dbh);
+ dbh.dbcc_size = sizeof(dbh);
+ dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
+
+ data->hNotify = RegisterDeviceNotification(data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
+ if (!data->hNotify) {
+ WIN_SetError("Failed to create notify device for joystick autodetect");
+ SDL_CleanupDeviceNotification(data);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
+{
+ MSG msg;
+
+ if (!data->messageWindow) {
+ return;
+ }
+
+ while (PeekMessage(&msg, data->messageWindow, 0, 0, PM_NOREMOVE)) {
+ if (GetMessage(&msg, data->messageWindow, 0, 0) != 0) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+}
+
+#endif /* __WINRT__ */
+
+/* Function/thread to scan the system for joysticks. */
+static int
+SDL_JoystickThread(void *_data)
+{
+ SDL_DeviceNotificationData notification_data;
+
+#if SDL_JOYSTICK_XINPUT
+ SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
+ SDL_zero(bOpenedXInputDevices);
+#endif
+
+ if (SDL_CreateDeviceNotification(¬ification_data) < 0) {
+ return -1;
+ }
+
+ SDL_LockMutex(s_mutexJoyStickEnum);
+ while (s_bJoystickThreadQuit == SDL_FALSE) {
+ SDL_bool bXInputChanged = SDL_FALSE;
+
+ SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 300);
+
+ SDL_CheckDeviceNotification(¬ification_data);
+
+#if SDL_JOYSTICK_XINPUT
+ if (SDL_XINPUT_Enabled() && XINPUTGETCAPABILITIES) {
+ /* scan for any change in XInput devices */
+ Uint8 userId;
+ for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
+ XINPUT_CAPABILITIES capabilities;
+ const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
+ const SDL_bool available = (result == ERROR_SUCCESS);
+ if (bOpenedXInputDevices[userId] != available) {
+ bXInputChanged = SDL_TRUE;
+ bOpenedXInputDevices[userId] = available;
+ }
+ }
+ }
+#endif /* SDL_JOYSTICK_XINPUT */
+
+ if (s_bWindowsDeviceChanged || bXInputChanged) {
+ SDL_UnlockMutex(s_mutexJoyStickEnum); /* let main thread go while we SDL_Delay(). */
+ SDL_Delay(300); /* wait for direct input to find out about this device */
+ SDL_LockMutex(s_mutexJoyStickEnum);
+
+ s_bDeviceRemoved = SDL_TRUE;
+ s_bDeviceAdded = SDL_TRUE;
+ s_bWindowsDeviceChanged = SDL_FALSE;
+ }
+ }
+ SDL_UnlockMutex(s_mutexJoyStickEnum);
+
+ SDL_CleanupDeviceNotification(¬ification_data);
+
+ return 1;
+}
+
+void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device)
+{
+ device->send_add_event = SDL_TRUE;
+ device->nInstanceID = ++s_nInstanceID;
+ device->pNext = SYS_Joystick;
+ SYS_Joystick = device;
+
+ s_bDeviceAdded = SDL_TRUE;
+}
+
+/* Function to scan the system for joysticks.
+ * This function should set SDL_numjoysticks to the number of available
+ * joysticks. Joystick 0 should be the system default joystick.
+ * It should return 0, or -1 on an unrecoverable fatal error.
+ */
+int
+SDL_SYS_JoystickInit(void)
+{
+ if (SDL_DINPUT_JoystickInit() < 0) {
+ SDL_SYS_JoystickQuit();
+ return -1;
+ }
+
+ if (SDL_XINPUT_JoystickInit() < 0) {
+ SDL_SYS_JoystickQuit();
+ return -1;
+ }
+
+ s_mutexJoyStickEnum = SDL_CreateMutex();
+ s_condJoystickThread = SDL_CreateCond();
+ s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
+
+ SDL_SYS_JoystickDetect();
+
+ if (!s_threadJoystick) {
+ s_bJoystickThreadQuit = SDL_FALSE;
+ /* spin up the thread to detect hotplug of devices */
+#if defined(__WIN32__) && !defined(HAVE_LIBC)
+#undef SDL_CreateThread
+#if SDL_DYNAMIC_API
+ s_threadJoystick= SDL_CreateThread_REAL(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
+#else
+ s_threadJoystick= SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
+#endif
+#else
+ s_threadJoystick = SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL);
+#endif
+ }
+ return SDL_SYS_NumJoysticks();
+}
+
+/* return the number of joysticks that are connected right now */
+int
+SDL_SYS_NumJoysticks()
+{
+ int nJoysticks = 0;
+ JoyStick_DeviceData *device = SYS_Joystick;
+ while (device) {
+ nJoysticks++;
+ device = device->pNext;
+ }
+
+ return nJoysticks;
+}
+
+/* detect any new joysticks being inserted into the system */
+void
+SDL_SYS_JoystickDetect()
+{
+ JoyStick_DeviceData *pCurList = NULL;
+#if !SDL_EVENTS_DISABLED
+ SDL_Event event;
+#endif
+
+ /* only enum the devices if the joystick thread told us something changed */
+ if (!s_bDeviceAdded && !s_bDeviceRemoved) {
+ return; /* thread hasn't signaled, nothing to do right now. */
+ }
+
+ SDL_LockMutex(s_mutexJoyStickEnum);
+
+ s_bDeviceAdded = SDL_FALSE;
+ s_bDeviceRemoved = SDL_FALSE;
+
+ pCurList = SYS_Joystick;
+ SYS_Joystick = NULL;
+
+ /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
+ SDL_DINPUT_JoystickDetect(&pCurList);
+
+ /* Look for XInput devices. Do this last, so they're first in the final list. */
+ SDL_XINPUT_JoystickDetect(&pCurList);
+
+ SDL_UnlockMutex(s_mutexJoyStickEnum);
+
+ while (pCurList) {
+ JoyStick_DeviceData *pListNext = NULL;
+
+ if (pCurList->bXInputDevice) {
+ SDL_XINPUT_MaybeRemoveDevice(pCurList->XInputUserId);
+ } else {
+ SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice);
+ }
+
+#if !SDL_EVENTS_DISABLED
+ SDL_zero(event);
+ event.type = SDL_JOYDEVICEREMOVED;
+
+ if (SDL_GetEventState(event.type) == SDL_ENABLE) {
+ event.jdevice.which = pCurList->nInstanceID;
+ if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
+ SDL_PushEvent(&event);
+ }
+ }
+#endif /* !SDL_EVENTS_DISABLED */
+
+ pListNext = pCurList->pNext;
+ SDL_free(pCurList->joystickname);
+ SDL_free(pCurList);
+ pCurList = pListNext;
+ }
+
+ if (s_bDeviceAdded) {
+ JoyStick_DeviceData *pNewJoystick;
+ int device_index = 0;
+ s_bDeviceAdded = SDL_FALSE;
+ pNewJoystick = SYS_Joystick;
+ while (pNewJoystick) {
+ if (pNewJoystick->send_add_event) {
+ if (pNewJoystick->bXInputDevice) {
+ SDL_XINPUT_MaybeAddDevice(pNewJoystick->XInputUserId);
+ } else {
+ SDL_DINPUT_MaybeAddDevice(&pNewJoystick->dxdevice);
+ }
+
+#if !SDL_EVENTS_DISABLED
+ SDL_zero(event);
+ event.type = SDL_JOYDEVICEADDED;
+
+ if (SDL_GetEventState(event.type) == SDL_ENABLE) {
+ event.jdevice.which = device_index;
+ if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
+ SDL_PushEvent(&event);
+ }
+ }
+#endif /* !SDL_EVENTS_DISABLED */
+ pNewJoystick->send_add_event = SDL_FALSE;
+ }
+ device_index++;
+ pNewJoystick = pNewJoystick->pNext;
+ }
+ }
+}
+
+/* Function to get the device-dependent name of a joystick */
+const char *
+SDL_SYS_JoystickNameForDeviceIndex(int device_index)
+{
+ JoyStick_DeviceData *device = SYS_Joystick;
+
+ for (; device_index > 0; device_index--)
+ device = device->pNext;
+
+ return device->joystickname;
+}
+
+/* Function to perform the mapping between current device instance and this joysticks instance id */
+SDL_JoystickID
+SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
+{
+ JoyStick_DeviceData *device = SYS_Joystick;
+ int index;
+
+ for (index = device_index; index > 0; index--)
+ device = device->pNext;
+
+ return device->nInstanceID;
+}
+
+/* Function to open a joystick for use.
+ The joystick to open is specified by the index field of the joystick.
+ This should fill the nbuttons and naxes fields of the joystick structure.
+ It returns 0, or -1 if there is an error.
+ */
+int
+SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
+{
+ JoyStick_DeviceData *joystickdevice = SYS_Joystick;
+
+ for (; device_index > 0; device_index--)
+ joystickdevice = joystickdevice->pNext;
+
+ /* allocate memory for system specific hardware data */
+ joystick->instance_id = joystickdevice->nInstanceID;
+ joystick->closed = SDL_FALSE;
+ joystick->hwdata =
+ (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
+ if (joystick->hwdata == NULL) {
+ return SDL_OutOfMemory();
+ }
+ SDL_zerop(joystick->hwdata);
+ joystick->hwdata->guid = joystickdevice->guid;
+
+ if (joystickdevice->bXInputDevice) {
+ return SDL_XINPUT_JoystickOpen(joystick, joystickdevice);
+ } else {
+ return SDL_DINPUT_JoystickOpen(joystick, joystickdevice);
+ }
+}
+
+/* return true if this joystick is plugged in right now */
+SDL_bool
+SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
+{
+ return !joystick->closed && !joystick->hwdata->removed;
+}
+
+void
+SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
+{
+ if (joystick->closed || !joystick->hwdata) {
+ return;
+ }
+
+ if (joystick->hwdata->bXInputDevice) {
+ SDL_XINPUT_JoystickUpdate(joystick);
+ } else {
+ SDL_DINPUT_JoystickUpdate(joystick);
+ }
+
+ if (joystick->hwdata->removed) {
+ joystick->closed = SDL_TRUE;
+ joystick->uncentered = SDL_TRUE;
+ }
+}
+
+/* Function to close a joystick after use */
+void
+SDL_SYS_JoystickClose(SDL_Joystick * joystick)
+{
+ if (joystick->hwdata->bXInputDevice) {
+ SDL_XINPUT_JoystickClose(joystick);
+ } else {
+ SDL_DINPUT_JoystickClose(joystick);
+ }
+
+ /* free system specific hardware data */
+ SDL_free(joystick->hwdata);
+
+ joystick->closed = SDL_TRUE;
+}
+
+/* Function to perform any system-specific joystick related cleanup */
+void
+SDL_SYS_JoystickQuit(void)
+{
+ JoyStick_DeviceData *device = SYS_Joystick;
+
+ while (device) {
+ JoyStick_DeviceData *device_next = device->pNext;
+ SDL_free(device->joystickname);
+ SDL_free(device);
+ device = device_next;
+ }
+ SYS_Joystick = NULL;
+
+ if (s_threadJoystick) {
+ SDL_LockMutex(s_mutexJoyStickEnum);
+ s_bJoystickThreadQuit = SDL_TRUE;
+ SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
+ SDL_UnlockMutex(s_mutexJoyStickEnum);
+ SDL_WaitThread(s_threadJoystick, NULL); /* wait for it to bugger off */
+
+ SDL_DestroyMutex(s_mutexJoyStickEnum);
+ SDL_DestroyCond(s_condJoystickThread);
+ s_condJoystickThread= NULL;
+ s_mutexJoyStickEnum = NULL;
+ s_threadJoystick = NULL;
+ }
+
+ SDL_DINPUT_JoystickQuit();
+ SDL_XINPUT_JoystickQuit();
+}
+
+/* return the stable device guid for this device index */
+SDL_JoystickGUID
+SDL_SYS_JoystickGetDeviceGUID(int device_index)
+{
+ JoyStick_DeviceData *device = SYS_Joystick;
+ int index;
+
+ for (index = device_index; index > 0; index--)
+ device = device->pNext;
+
+ return device->guid;
+}
+
+SDL_JoystickGUID
+SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
+{
+ return joystick->hwdata->guid;
+}
+
+#endif /* SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/windows/SDL_windowsjoystick_c.h b/src/joystick/windows/SDL_windowsjoystick_c.h
new file mode 100644
index 000000000..703b0ccd9
--- /dev/null
+++ b/src/joystick/windows/SDL_windowsjoystick_c.h
@@ -0,0 +1,89 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_events.h"
+#include "SDL_joystick.h"
+#include "../SDL_sysjoystick.h"
+#include "../../core/windows/SDL_windows.h"
+#include "../../core/windows/SDL_directx.h"
+
+#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */
+
+typedef struct JoyStick_DeviceData
+{
+ SDL_JoystickGUID guid;
+ char *joystickname;
+ Uint8 send_add_event;
+ SDL_JoystickID nInstanceID;
+ SDL_bool bXInputDevice;
+ BYTE SubType;
+ Uint8 XInputUserId;
+ DIDEVICEINSTANCE dxdevice;
+ struct JoyStick_DeviceData *pNext;
+} JoyStick_DeviceData;
+
+extern JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
+
+typedef enum Type
+{
+ BUTTON,
+ AXIS,
+ HAT
+} Type;
+
+typedef struct input_t
+{
+ /* DirectInput offset for this input type: */
+ DWORD ofs;
+
+ /* Button, axis or hat: */
+ Type type;
+
+ /* SDL input offset: */
+ Uint8 num;
+} input_t;
+
+/* The private structure used to keep track of a joystick */
+struct joystick_hwdata
+{
+ SDL_JoystickGUID guid;
+ SDL_bool removed;
+ SDL_bool send_remove_event;
+
+#if SDL_JOYSTICK_DINPUT
+ LPDIRECTINPUTDEVICE8 InputDevice;
+ DIDEVCAPS Capabilities;
+ SDL_bool buffered;
+ input_t Inputs[MAX_INPUTS];
+ int NumInputs;
+ int NumSliders;
+#endif
+
+ SDL_bool bXInputDevice; /* SDL_TRUE if this device supports using the xinput API rather than DirectInput */
+ SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
+ Uint8 userid; /* XInput userid index for this joystick */
+ DWORD dwPacketNumber;
+};
+
+extern void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device);
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c
new file mode 100644
index 000000000..4a625a5eb
--- /dev/null
+++ b/src/joystick/windows/SDL_xinputjoystick.c
@@ -0,0 +1,390 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_assert.h"
+#include "SDL_hints.h"
+#include "../SDL_sysjoystick.h"
+#include "SDL_windowsjoystick_c.h"
+#include "SDL_xinputjoystick_c.h"
+
+
+#if SDL_JOYSTICK_XINPUT
+
+/*
+ * Internal stuff.
+ */
+static SDL_bool s_bXInputEnabled = SDL_TRUE;
+
+
+static SDL_bool
+SDL_XInputUseOldJoystickMapping()
+{
+ static int s_XInputUseOldJoystickMapping = -1;
+ if (s_XInputUseOldJoystickMapping < 0) {
+ const char *hint = SDL_GetHint(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING);
+ s_XInputUseOldJoystickMapping = (hint && *hint == '1') ? 1 : 0;
+ }
+ return (s_XInputUseOldJoystickMapping > 0);
+}
+
+SDL_bool SDL_XINPUT_Enabled(void)
+{
+ return s_bXInputEnabled;
+}
+
+int
+SDL_XINPUT_JoystickInit(void)
+{
+ const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
+ if (env && !SDL_atoi(env)) {
+ s_bXInputEnabled = SDL_FALSE;
+ }
+
+ if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
+ s_bXInputEnabled = SDL_FALSE; /* oh well. */
+ }
+ return 0;
+}
+
+static char *
+GetXInputName(const Uint8 userid, BYTE SubType)
+{
+ char name[32];
+
+ if (SDL_XInputUseOldJoystickMapping()) {
+ SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid);
+ } else {
+ switch (SubType) {
+ case XINPUT_DEVSUBTYPE_GAMEPAD:
+ SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid);
+ break;
+ case XINPUT_DEVSUBTYPE_WHEEL:
+ SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid);
+ break;
+ case XINPUT_DEVSUBTYPE_ARCADE_STICK:
+ SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid);
+ break;
+ case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
+ SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid);
+ break;
+ case XINPUT_DEVSUBTYPE_DANCE_PAD:
+ SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + userid);
+ break;
+ case XINPUT_DEVSUBTYPE_GUITAR:
+ case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
+ case XINPUT_DEVSUBTYPE_GUITAR_BASS:
+ SDL_snprintf(name, sizeof(name), "XInput Guitar #%u", 1 + userid);
+ break;
+ case XINPUT_DEVSUBTYPE_DRUM_KIT:
+ SDL_snprintf(name, sizeof(name), "XInput DrumKit #%u", 1 + userid);
+ break;
+ case XINPUT_DEVSUBTYPE_ARCADE_PAD:
+ SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%u", 1 + userid);
+ break;
+ default:
+ SDL_snprintf(name, sizeof(name), "XInput Device #%u", 1 + userid);
+ break;
+ }
+ }
+ return SDL_strdup(name);
+}
+
+static void
+AddXInputDevice(const Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
+{
+ JoyStick_DeviceData *pPrevJoystick = NULL;
+ JoyStick_DeviceData *pNewJoystick = *pContext;
+
+ if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
+ return;
+
+ if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN)
+ return;
+
+ while (pNewJoystick) {
+ if (pNewJoystick->bXInputDevice && (pNewJoystick->XInputUserId == userid) && (pNewJoystick->SubType == SubType)) {
+ /* if we are replacing the front of the list then update it */
+ if (pNewJoystick == *pContext) {
+ *pContext = pNewJoystick->pNext;
+ } else if (pPrevJoystick) {
+ pPrevJoystick->pNext = pNewJoystick->pNext;
+ }
+
+ pNewJoystick->pNext = SYS_Joystick;
+ SYS_Joystick = pNewJoystick;
+ return; /* already in the list. */
+ }
+
+ pPrevJoystick = pNewJoystick;
+ pNewJoystick = pNewJoystick->pNext;
+ }
+
+ pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
+ if (!pNewJoystick) {
+ return; /* better luck next time? */
+ }
+ SDL_zerop(pNewJoystick);
+
+ pNewJoystick->joystickname = GetXInputName(userid, SubType);
+ if (!pNewJoystick->joystickname) {
+ SDL_free(pNewJoystick);
+ return; /* better luck next time? */
+ }
+
+ pNewJoystick->bXInputDevice = SDL_TRUE;
+ if (SDL_XInputUseOldJoystickMapping()) {
+ SDL_zero(pNewJoystick->guid);
+ } else {
+ pNewJoystick->guid.data[0] = 'x';
+ pNewJoystick->guid.data[1] = 'i';
+ pNewJoystick->guid.data[2] = 'n';
+ pNewJoystick->guid.data[3] = 'p';
+ pNewJoystick->guid.data[4] = 'u';
+ pNewJoystick->guid.data[5] = 't';
+ pNewJoystick->guid.data[6] = SubType;
+ }
+ pNewJoystick->SubType = SubType;
+ pNewJoystick->XInputUserId = userid;
+ SDL_SYS_AddJoystickDevice(pNewJoystick);
+}
+
+void
+SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
+{
+ int iuserid;
+
+ if (!s_bXInputEnabled) {
+ return;
+ }
+
+ /* iterate in reverse, so these are in the final list in ascending numeric order. */
+ for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
+ const Uint8 userid = (Uint8)iuserid;
+ XINPUT_CAPABILITIES capabilities;
+ if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
+ AddXInputDevice(userid, capabilities.SubType, pContext);
+ }
+ }
+}
+
+int
+SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
+{
+ const Uint8 userId = joystickdevice->XInputUserId;
+ XINPUT_CAPABILITIES capabilities;
+ XINPUT_VIBRATION state;
+
+ SDL_assert(s_bXInputEnabled);
+ SDL_assert(XINPUTGETCAPABILITIES);
+ SDL_assert(XINPUTSETSTATE);
+ SDL_assert(userId >= 0);
+ SDL_assert(userId < XUSER_MAX_COUNT);
+
+ joystick->hwdata->bXInputDevice = SDL_TRUE;
+
+ if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
+ SDL_free(joystick->hwdata);
+ joystick->hwdata = NULL;
+ return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
+ }
+ SDL_zero(state);
+ joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS);
+ joystick->hwdata->userid = userId;
+
+ /* The XInput API has a hard coded button/axis mapping, so we just match it */
+ if (SDL_XInputUseOldJoystickMapping()) {
+ joystick->naxes = 6;
+ joystick->nbuttons = 15;
+ } else {
+ joystick->naxes = 6;
+ joystick->nbuttons = 11;
+ joystick->nhats = 1;
+ }
+ return 0;
+}
+
+static void
+UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
+{
+ static WORD s_XInputButtons[] = {
+ XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
+ XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_GUIDE
+ };
+ WORD wButtons = pXInputState->Gamepad.wButtons;
+ Uint8 button;
+ Uint8 hat = SDL_HAT_CENTERED;
+
+ SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
+ SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
+ SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX);
+ SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
+ SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
+ SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
+
+ for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
+ SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
+ }
+}
+
+static void
+UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
+{
+ static WORD s_XInputButtons[] = {
+ XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_GUIDE
+ };
+ WORD wButtons = pXInputState->Gamepad.wButtons;
+ Uint8 button;
+ Uint8 hat = SDL_HAT_CENTERED;
+
+ SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
+ SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
+ SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
+ SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX);
+ SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
+ SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
+
+ for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
+ SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
+ }
+
+ if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
+ hat |= SDL_HAT_UP;
+ }
+ if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
+ hat |= SDL_HAT_DOWN;
+ }
+ if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
+ hat |= SDL_HAT_LEFT;
+ }
+ if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
+ hat |= SDL_HAT_RIGHT;
+ }
+ SDL_PrivateJoystickHat(joystick, 0, hat);
+}
+
+void
+SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
+{
+ HRESULT result;
+ XINPUT_STATE_EX XInputState;
+
+ if (!XINPUTGETSTATE)
+ return;
+
+ result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
+ if (result == ERROR_DEVICE_NOT_CONNECTED) {
+ joystick->hwdata->send_remove_event = SDL_TRUE;
+ joystick->hwdata->removed = SDL_TRUE;
+ return;
+ }
+
+ /* only fire events if the data changed from last time */
+ if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
+ if (SDL_XInputUseOldJoystickMapping()) {
+ UpdateXInputJoystickState_OLD(joystick, &XInputState);
+ } else {
+ UpdateXInputJoystickState(joystick, &XInputState);
+ }
+ joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
+ }
+}
+
+void
+SDL_XINPUT_JoystickClose(SDL_Joystick * joystick)
+{
+}
+
+void
+SDL_XINPUT_JoystickQuit(void)
+{
+ if (s_bXInputEnabled) {
+ WIN_UnloadXInputDLL();
+ }
+}
+
+SDL_bool
+SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
+{
+ JoyStick_DeviceData *device = SYS_Joystick;
+ int index;
+
+ for (index = device_index; index > 0; index--)
+ device = device->pNext;
+
+ return (device->SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
+}
+
+#else /* !SDL_JOYSTICK_XINPUT */
+
+
+SDL_bool SDL_XINPUT_Enabled(void)
+{
+ return SDL_FALSE;
+}
+
+int
+SDL_XINPUT_JoystickInit(void)
+{
+ return 0;
+}
+
+void
+SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
+{
+}
+
+int
+SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
+{
+ return SDL_Unsupported();
+}
+
+void
+SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
+{
+}
+
+void
+SDL_XINPUT_JoystickClose(SDL_Joystick * joystick)
+{
+}
+
+void
+SDL_XINPUT_JoystickQuit(void)
+{
+}
+
+SDL_bool
+SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
+{
+ return SDL_FALSE;
+}
+
+#endif /* SDL_JOYSTICK_XINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/windows/SDL_xinputjoystick_c.h b/src/joystick/windows/SDL_xinputjoystick_c.h
new file mode 100644
index 000000000..825c29209
--- /dev/null
+++ b/src/joystick/windows/SDL_xinputjoystick_c.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "../../core/windows/SDL_xinput.h"
+
+extern SDL_bool SDL_XINPUT_Enabled(void);
+extern int SDL_XINPUT_JoystickInit(void);
+extern void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
+extern int SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
+extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick);
+extern void SDL_XINPUT_JoystickClose(SDL_Joystick * joystick);
+extern void SDL_XINPUT_JoystickQuit(void);
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/winrt/SDL_xinputjoystick.c b/src/joystick/winrt/SDL_xinputjoystick.c
deleted file mode 100644
index 197d50546..000000000
--- a/src/joystick/winrt/SDL_xinputjoystick.c
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2014 Sam Lantinga
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-*/
-#include "../../SDL_internal.h"
-
-#if SDL_JOYSTICK_XINPUT
-
-/* SDL_xinputjoystick.c implements an XInput-only joystick and game controller
- backend that is suitable for use on WinRT. SDL's DirectInput backend, also
- XInput-capable, was not used as DirectInput is not available on WinRT (or,
- at least, it isn't a public API). Some portions of this XInput backend
- may copy parts of the XInput-using code from the DirectInput backend.
- Refactoring the common parts into one location may be good to-do at some
- point.
-
- TODO, WinRT: add hotplug support for XInput based game controllers
-*/
-
-#include "SDL_joystick.h"
-#include "../SDL_sysjoystick.h"
-#include "../SDL_joystick_c.h"
-#include "SDL_events.h"
-#include "../../events/SDL_events_c.h"
-#include "SDL_timer.h"
-
-#include
-#include
-
-#ifndef XINPUT_GAMEPAD_GUIDE
-#define XINPUT_GAMEPAD_GUIDE 0x0400
-#endif
-
-struct joystick_hwdata {
- //Uint8 bXInputHaptic; // Supports force feedback via XInput.
- DWORD userIndex; // The XInput device index, in the range [0, XUSER_MAX_COUNT-1] (probably [0,3]).
- XINPUT_STATE XInputState; // the last-read in XInputState, kept around to compare old and new values
- SDL_bool isDeviceConnected; // was the device connected (on the last detection-polling, or during backend-initialization)?
- SDL_bool isDeviceConnectionEventPending; // was a device added, and is the associated add-event pending?
- SDL_bool isDeviceRemovalEventPending; // was the device removed, and is the associated remove-event pending?
-};
-
-/* Keep track of data on all XInput devices, regardless of whether or not
- they've been opened (via SDL_JoystickOpen).
- */
-static struct joystick_hwdata g_XInputData[XUSER_MAX_COUNT];
-
-/* Device detection can be extremely costly performance-wise, in some cases.
- In particular, if no devices are connected, calls to detect a single device,
- via either XInputGetState() or XInputGetCapabilities(), can take upwards of
- 20 ms on a 1st generation Surface RT, more if devices are detected across
- all of of XInput's four device slots. WinRT and XInput do not appear to
- have callback-based APIs to notify an app when a device is connected, at
- least as of Windows 8.1. The synchronous XInput calls must be used.
-
- Once a device is connected, calling XInputGetState() is a much less costly
- operation, with individual calls costing well under 1 ms, and often under
- 0.1 ms [on a 1st gen Surface RT].
-
- With XInput's performance limitations in mind, a separate device-detection
- thread will be utilized (by SDL) to try to move costly XInput calls off the
- main thread. Polling of active devices still, however, occurs on the main
- thread.
- */
-static SDL_Thread * g_DeviceDetectionThread = NULL;
-static SDL_mutex * g_DeviceInfoLock = NULL;
-static SDL_bool g_DeviceDetectionQuit = SDL_FALSE;
-
-/* Main function for the device-detection thread.
- */
-static int
-DeviceDetectionThreadMain(void * _data)
-{
- DWORD result;
- XINPUT_CAPABILITIES tempXInputCaps;
- int i;
-
- while (1) {
- /* See if the device-detection thread is being asked to shutdown.
- */
- SDL_LockMutex(g_DeviceInfoLock);
- if (g_DeviceDetectionQuit) {
- SDL_UnlockMutex(g_DeviceInfoLock);
- break;
- }
- SDL_UnlockMutex(g_DeviceInfoLock);
-
- /* Add a short delay to prevent the device-detection thread from eating
- up too much CPU time:
- */
- SDL_Delay(300);
-
- /* TODO, WinRT: try making the device-detection thread wakeup sooner from its CPU-preserving SDL_Delay, if the thread was asked to quit.
- */
-
- /* See if any new devices are connected. */
- SDL_LockMutex(g_DeviceInfoLock);
- for (i = 0; i < XUSER_MAX_COUNT; ++i) {
- if (!g_XInputData[i].isDeviceConnected &&
- !g_XInputData[i].isDeviceConnectionEventPending &&
- !g_XInputData[i].isDeviceRemovalEventPending)
- {
- SDL_UnlockMutex(g_DeviceInfoLock);
- result = XInputGetCapabilities(i, 0, &tempXInputCaps);
- SDL_LockMutex(g_DeviceInfoLock);
- if (result == ERROR_SUCCESS) {
- /* Yes, a device is connected. Mark it as such.
- Others will be told about this (via an
- SDL_JOYDEVICEADDED event) in the next call to
- SDL_SYS_JoystickDetect.
- */
- g_XInputData[i].isDeviceConnected = SDL_TRUE;
- g_XInputData[i].isDeviceConnectionEventPending = SDL_TRUE;
- }
- }
- }
- SDL_UnlockMutex(g_DeviceInfoLock);
- }
-
- return 0;
-}
-
-/* Function to scan the system for joysticks.
- * It should return 0, or -1 on an unrecoverable fatal error.
- */
-int
-SDL_SYS_JoystickInit(void)
-{
- HRESULT result = S_OK;
- XINPUT_STATE tempXInputState;
- int i;
-
- SDL_zero(g_XInputData);
-
- /* Make initial notes on whether or not devices are connected (or not).
- */
- for (i = 0; i < XUSER_MAX_COUNT; ++i) {
- result = XInputGetState(i, &tempXInputState);
- if (result == ERROR_SUCCESS) {
- g_XInputData[i].isDeviceConnected = SDL_TRUE;
- }
- }
-
- /* Start up the device-detection thread.
- */
- g_DeviceDetectionQuit = SDL_FALSE;
- g_DeviceInfoLock = SDL_CreateMutex();
- g_DeviceDetectionThread = SDL_CreateThread(DeviceDetectionThreadMain, "SDL_joystick", NULL);
-
- return (0);
-}
-
-int SDL_SYS_NumJoysticks()
-{
- int joystickCount = 0;
- DWORD i;
-
- /* Iterate through each possible XInput device and see if something
- was connected (at joystick init, or during the last polling).
- */
- SDL_LockMutex(g_DeviceInfoLock);
- for (i = 0; i < XUSER_MAX_COUNT; ++i) {
- if (g_XInputData[i].isDeviceConnected) {
- ++joystickCount;
- }
- }
- SDL_UnlockMutex(g_DeviceInfoLock);
-
- return joystickCount;
-}
-
-void SDL_SYS_JoystickDetect()
-{
- DWORD i;
- SDL_Event event;
-
- /* Iterate through each possible XInput device, seeing if any devices
- have been connected, or if they were removed.
- */
- SDL_LockMutex(g_DeviceInfoLock);
- for (i = 0; i < XUSER_MAX_COUNT; ++i) {
- /* See if any new devices are connected. */
- if (g_XInputData[i].isDeviceConnectionEventPending) {
-#if !SDL_EVENTS_DISABLED
- SDL_zero(event);
- event.type = SDL_JOYDEVICEADDED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = i;
- if ((SDL_EventOK == NULL)
- || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif
- g_XInputData[i].isDeviceConnectionEventPending = SDL_FALSE;
- } else if (g_XInputData[i].isDeviceRemovalEventPending) {
- /* A device was previously marked as removed (by
- SDL_SYS_JoystickUpdate). Tell others about the device removal.
- */
-
- g_XInputData[i].isDeviceRemovalEventPending = SDL_FALSE;
-
-#if !SDL_EVENTS_DISABLED
- SDL_zero(event);
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = i; //joystick->hwdata->userIndex;
- if ((SDL_EventOK == NULL)
- || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif
- }
- }
- SDL_UnlockMutex(g_DeviceInfoLock);
-}
-
-
-/* Internal function to retreive device capabilities.
- This function will return an SDL-standard value of 0 on success
- (a device is connected, and data on it was retrieved), or -1
- on failure (no device was connected, or some other error
- occurred. SDL_SetError() will be invoked to set an appropriate
- error message.
- */
-static int
-SDL_XInput_GetDeviceCapabilities(int device_index, XINPUT_CAPABILITIES * pDeviceCaps)
-{
- HRESULT dwResult;
-
- /* Make sure that the device index is a valid one. If not, return to the
- caller with an error.
- */
- if (device_index < 0 || device_index >= XUSER_MAX_COUNT) {
- return SDL_SetError("invalid/unavailable device index");
- }
-
- /* See if a device exists, and if so, what its capabilities are. If a
- device is not available, return to the caller with an error.
- */
- switch ((dwResult = XInputGetCapabilities(device_index, 0, pDeviceCaps))) {
- case ERROR_SUCCESS:
- /* A device is available, and its capabilities were retrieved! */
- return 0;
- case ERROR_DEVICE_NOT_CONNECTED:
- return SDL_SetError("no device is connected at joystick index, %d", device_index);
- default:
- return SDL_SetError("an unknown error occurred when retrieving info on a device at joystick index, %d", device_index);
- }
-}
-
-/* Function to get the device-dependent name of a joystick */
-const char *
-SDL_SYS_JoystickNameForDeviceIndex(int device_index)
-{
- XINPUT_CAPABILITIES deviceCaps;
-
- if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
- /* Uh oh. Device capabilities couldn't be retrieved. Return to the
- caller. SDL_SetError() has already been invoked (with relevant
- information).
- */
- return NULL;
- }
-
- switch (deviceCaps.SubType) {
- default:
- if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
- return "Undefined game controller";
- } else {
- return "Undefined controller";
- }
- case XINPUT_DEVSUBTYPE_UNKNOWN:
- if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
- return "Unknown game controller";
- } else {
- return "Unknown controller";
- }
- case XINPUT_DEVSUBTYPE_GAMEPAD:
- return "Gamepad controller";
- case XINPUT_DEVSUBTYPE_WHEEL:
- return "Racing wheel controller";
- case XINPUT_DEVSUBTYPE_ARCADE_STICK:
- return "Arcade stick controller";
- case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
- return "Flight stick controller";
- case XINPUT_DEVSUBTYPE_DANCE_PAD:
- return "Dance pad controller";
- case XINPUT_DEVSUBTYPE_GUITAR:
- return "Guitar controller";
- case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
- return "Guitar controller, Alternate";
- case XINPUT_DEVSUBTYPE_GUITAR_BASS:
- return "Guitar controller, Bass";
- case XINPUT_DEVSUBTYPE_DRUM_KIT:
- return "Drum controller";
- case XINPUT_DEVSUBTYPE_ARCADE_PAD:
- return "Arcade pad controller";
- }
-}
-
-/* Function to perform the mapping from device index to the instance id for this index */
-SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
-{
- return device_index;
-}
-
-/* Function to open a joystick for use.
- The joystick to open is specified by the index field of the joystick.
- This should fill the nbuttons and naxes fields of the joystick structure.
- It returns 0, or -1 if there is an error.
- */
-int
-SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
-{
- XINPUT_CAPABILITIES deviceCaps;
-
- if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
- /* Uh oh. Device capabilities couldn't be retrieved. Return to the
- caller. SDL_SetError() has already been invoked (with relevant
- information).
- */
- return -1;
- }
-
- /* For now, only game pads are supported. If the device is something other
- than that, return an error to the caller.
- */
- if (deviceCaps.Type != XINPUT_DEVTYPE_GAMEPAD) {
- return SDL_SetError("a device is connected (at joystick index, %d), but it is of an unknown device type (deviceCaps.Flags=%ul)",
- device_index, (unsigned int)deviceCaps.Flags);
- }
-
- /* Create the joystick data structure */
- joystick->instance_id = device_index;
- joystick->hwdata = &g_XInputData[device_index];
-
- // The XInput API has a hard coded button/axis mapping, so we just match it
- joystick->naxes = 6;
- joystick->nbuttons = 15;
- joystick->nballs = 0;
- joystick->nhats = 0;
-
- /* We're done! */
- return (0);
-}
-
-/* Function to determine is this joystick is attached to the system right now */
-SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
-{
- SDL_bool isDeviceConnected;
- SDL_LockMutex(g_DeviceInfoLock);
- isDeviceConnected = joystick->hwdata->isDeviceConnected;
- SDL_UnlockMutex(g_DeviceInfoLock);
- return isDeviceConnected;
-}
-
-/* Function to return > 0 if a bit array of buttons differs after applying a mask
-*/
-static int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
-{
- return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
-}
-
-/* This is an almost-identical copy of UpdateXInputJoystickState from the
- DirectInput + XInput backend.
-
- TODO, WinRT: look into making the DirectInput+Xinput and WinRT/XInput joystick backends share more code, without duplication
- TODO, WinRT: consider adding support for the "old" XInput controller mapping (via SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING)
-*/
-static void
-UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE *pXInputState)
-{
- static WORD s_XInputButtons[] = {
- XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
- XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
- XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
- XINPUT_GAMEPAD_GUIDE
- };
- WORD wButtons = pXInputState->Gamepad.wButtons;
- Uint8 button;
- Uint8 hat = SDL_HAT_CENTERED;
-
- SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
- SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
- SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
- SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX);
- SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
- SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
-
- for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
- SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
- }
-
- if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
- hat |= SDL_HAT_UP;
- }
- if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
- hat |= SDL_HAT_DOWN;
- }
- if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
- hat |= SDL_HAT_LEFT;
- }
- if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
- hat |= SDL_HAT_RIGHT;
- }
- SDL_PrivateJoystickHat(joystick, 0, hat);
-}
-
-/* Function to update the state of a joystick - called as a device poll.
- * This function shouldn't update the joystick structure directly,
- * but instead should call SDL_PrivateJoystick*() to deliver events
- * and update joystick device state.
- */
-void
-SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
-{
- HRESULT result;
- XINPUT_STATE prevXInputState;
-
- SDL_LockMutex(g_DeviceInfoLock);
-
- /* Before polling for new data, make note of the old data */
- prevXInputState = joystick->hwdata->XInputState;
-
- /* Poll for new data */
- result = XInputGetState(joystick->hwdata->userIndex, &joystick->hwdata->XInputState);
- if (result == ERROR_DEVICE_NOT_CONNECTED) {
- if (joystick->hwdata->isDeviceConnected) {
- joystick->hwdata->isDeviceConnected = SDL_FALSE;
- joystick->hwdata->isDeviceRemovalEventPending = SDL_TRUE;
- /* TODO, WinRT: make sure isDeviceRemovalEventPending gets cleared as appropriate, and that quick re-plugs don't cause trouble */
- }
- SDL_UnlockMutex(g_DeviceInfoLock);
- return;
- }
-
- /* Make sure the device is marked as connected */
- joystick->hwdata->isDeviceConnected = SDL_TRUE;
-
- // only fire events if the data changed from last time
- if ( joystick->hwdata->XInputState.dwPacketNumber != 0
- && joystick->hwdata->XInputState.dwPacketNumber != prevXInputState.dwPacketNumber )
- {
- XINPUT_STATE *pXInputState = &joystick->hwdata->XInputState;
- UpdateXInputJoystickState(joystick, pXInputState);
- }
-
- SDL_UnlockMutex(g_DeviceInfoLock);
-}
-
-/* Function to close a joystick after use */
-void
-SDL_SYS_JoystickClose(SDL_Joystick * joystick)
-{
- /* Clear cached button data on the joystick */
- SDL_LockMutex(g_DeviceInfoLock);
- SDL_zero(joystick->hwdata->XInputState);
- SDL_UnlockMutex(g_DeviceInfoLock);
-
- /* There's need to free 'hwdata', as it's a pointer to a global array.
- The field will be cleared anyways, just to indicate that it's not
- currently needed.
- */
- joystick->hwdata = NULL;
-}
-
-/* Function to perform any system-specific joystick related cleanup */
-void
-SDL_SYS_JoystickQuit(void)
-{
- /* Tell the joystick detection thread to stop, then wait for it to finish */
- SDL_LockMutex(g_DeviceInfoLock);
- g_DeviceDetectionQuit = SDL_TRUE;
- SDL_UnlockMutex(g_DeviceInfoLock);
- SDL_WaitThread(g_DeviceDetectionThread, NULL);
-
- /* Clean up device-detection stuff */
- SDL_DestroyMutex(g_DeviceInfoLock);
- g_DeviceInfoLock = NULL;
- g_DeviceDetectionThread = NULL;
- g_DeviceDetectionQuit = SDL_FALSE;
-
- return;
-}
-
-SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
-{
- SDL_JoystickGUID guid;
- // the GUID is just the first 16 chars of the name for now
- const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
- SDL_zero( guid );
- SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
- return guid;
-}
-
-
-SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
-{
- SDL_JoystickGUID guid;
- // the GUID is just the first 16 chars of the name for now
- const char *name = joystick->name;
- SDL_zero( guid );
- SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
- return guid;
-}
-
-SDL_bool SDL_SYS_IsXInputDeviceIndex(int device_index)
-{
- /* The XInput-capable DirectInput joystick backend implements the same
- function (SDL_SYS_IsXInputDeviceIndex), however in that case, not all
- joystick devices are XInput devices. In this case, with the
- WinRT-enabled XInput-only backend, all "joystick" devices are XInput
- devices.
- */
- return SDL_TRUE;
-}
-
-SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
-{
- XINPUT_CAPABILITIES deviceCaps;
-
- if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
- return SDL_FALSE;
- }
-
- return (deviceCaps.SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
-}
-
-#endif /* SDL_JOYSTICK_XINPUT */
-
-/* vi: set ts=4 sw=4 expandtab: */