zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_dxjoystick.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 #ifdef SDL_JOYSTICK_DINPUT
24 
25 /* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
26  * A. Formiga's WINMM driver.
27  *
28  * Hats and sliders are completely untested; the app I'm writing this for mostly
29  * doesn't use them and I don't own any joysticks with them.
30  *
31  * We don't bother to use event notification here. It doesn't seem to work
32  * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
33  * let it return 0 events. */
34 
35 #include "SDL_error.h"
36 #include "SDL_assert.h"
37 #include "SDL_events.h"
38 #include "SDL_thread.h"
39 #include "SDL_timer.h"
40 #include "SDL_mutex.h"
41 #include "SDL_events.h"
42 #include "SDL_hints.h"
43 #include "SDL_joystick.h"
44 #include "../SDL_sysjoystick.h"
45 #if !SDL_EVENTS_DISABLED
46 #include "../../events/SDL_events_c.h"
47 #endif
48 
49 #define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
50 #include "SDL_dxjoystick_c.h"
51 
52 #ifndef DIDFT_OPTIONAL
53 #define DIDFT_OPTIONAL 0x80000000
54 #endif
55 
56 
57 #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
58 #define AXIS_MIN -32768 /* minimum value for axis coordinate */
59 #define AXIS_MAX 32767 /* maximum value for axis coordinate */
60 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
61 
62 /* external variables referenced. */
63 extern HWND SDL_HelperWindow;
64 
65 
66 /* local variables */
67 static SDL_bool coinitialized = SDL_FALSE;
68 static LPDIRECTINPUT8 dinput = NULL;
69 static SDL_bool s_bDeviceAdded = SDL_FALSE;
70 static SDL_bool s_bDeviceRemoved = SDL_FALSE;
71 static SDL_JoystickID s_nInstanceID = -1;
72 static SDL_cond *s_condJoystickThread = NULL;
73 static SDL_mutex *s_mutexJoyStickEnum = NULL;
74 static SDL_Thread *s_threadJoystick = NULL;
75 static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
76 static SDL_bool s_bXInputEnabled = SDL_TRUE;
77 
78 XInputGetState_t SDL_XInputGetState = NULL;
79 XInputSetState_t SDL_XInputSetState = NULL;
80 XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
82 
83 static HANDLE s_pXInputDLL = 0;
84 static int s_XInputDLLRefCount = 0;
85 
86 int
88 {
89  DWORD version = 0;
90 
91  if (s_pXInputDLL) {
92  SDL_assert(s_XInputDLLRefCount > 0);
93  s_XInputDLLRefCount++;
94  return 0; /* already loaded */
95  }
96 
97  version = (1 << 16) | 4;
98  s_pXInputDLL = LoadLibrary( L"XInput1_4.dll" ); /* 1.4 Ships with Windows 8. */
99  if (!s_pXInputDLL) {
100  version = (1 << 16) | 3;
101  s_pXInputDLL = LoadLibrary( L"XInput1_3.dll" ); /* 1.3 Ships with Vista and Win7, can be installed as a redistributable component. */
102  }
103  if (!s_pXInputDLL) {
104  s_pXInputDLL = LoadLibrary( L"bin\\XInput1_3.dll" );
105  }
106  if (!s_pXInputDLL) {
107  return -1;
108  }
109 
110  SDL_assert(s_XInputDLLRefCount == 0);
112  s_XInputDLLRefCount = 1;
113 
114  /* 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... */
115  SDL_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, (LPCSTR)100 );
116  SDL_XInputSetState = (XInputSetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputSetState" );
117  SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetCapabilities" );
120  return -1;
121  }
122 
123  return 0;
124 }
125 
126 void
128 {
129  if ( s_pXInputDLL ) {
130  SDL_assert(s_XInputDLLRefCount > 0);
131  if (--s_XInputDLLRefCount == 0) {
132  FreeLibrary( s_pXInputDLL );
133  s_pXInputDLL = NULL;
134  }
135  } else {
136  SDL_assert(s_XInputDLLRefCount == 0);
137  }
138 }
139 
140 
141 extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
142  LPDIRECTINPUT * ppDI,
143  LPUNKNOWN punkOuter);
144 struct JoyStick_DeviceData_
145 {
146  SDL_JoystickGUID guid;
147  DIDEVICEINSTANCE dxdevice;
148  char *joystickname;
149  Uint8 send_add_event;
150  SDL_JoystickID nInstanceID;
151  SDL_bool bXInputDevice;
152  Uint8 XInputUserId;
153  struct JoyStick_DeviceData_ *pNext;
154 };
155 
156 typedef struct JoyStick_DeviceData_ JoyStick_DeviceData;
157 
158 static JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
159 
160 /* local prototypes */
161 static int SetDIerror(const char *function, HRESULT code);
162 static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE *
163  pdidInstance, VOID * pContext);
164 static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev,
165  LPVOID pvRef);
166 static void SortDevObjects(SDL_Joystick *joystick);
167 static Uint8 TranslatePOV(DWORD value);
168 static int SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis,
169  Sint16 value);
170 static int SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat,
171  Uint8 value);
172 static int SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick,
173  Uint8 button, Uint8 state);
174 
175 /* Taken from Wine - Thanks! */
176 DIOBJECTDATAFORMAT dfDIJoystick2[] = {
177  { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
178  { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
179  { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
180  { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
181  { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
182  { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
183  { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
184  { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
185  { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
186  { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
187  { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
188  { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
189  { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
190  { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
191  { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
192  { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
193  { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
194  { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
195  { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
196  { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
197  { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
198  { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
199  { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
200  { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
201  { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
202  { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
203  { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
204  { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
205  { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
206  { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
207  { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
208  { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
209  { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
210  { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
211  { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
212  { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
213  { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
214  { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
215  { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
216  { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
217  { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
218  { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
219  { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
220  { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
221  { NULL,DIJOFS_BUTTON(32),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
222  { NULL,DIJOFS_BUTTON(33),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
223  { NULL,DIJOFS_BUTTON(34),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
224  { NULL,DIJOFS_BUTTON(35),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
225  { NULL,DIJOFS_BUTTON(36),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
226  { NULL,DIJOFS_BUTTON(37),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
227  { NULL,DIJOFS_BUTTON(38),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
228  { NULL,DIJOFS_BUTTON(39),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
229  { NULL,DIJOFS_BUTTON(40),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
230  { NULL,DIJOFS_BUTTON(41),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
231  { NULL,DIJOFS_BUTTON(42),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
232  { NULL,DIJOFS_BUTTON(43),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
233  { NULL,DIJOFS_BUTTON(44),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
234  { NULL,DIJOFS_BUTTON(45),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
235  { NULL,DIJOFS_BUTTON(46),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
236  { NULL,DIJOFS_BUTTON(47),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
237  { NULL,DIJOFS_BUTTON(48),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
238  { NULL,DIJOFS_BUTTON(49),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
239  { NULL,DIJOFS_BUTTON(50),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
240  { NULL,DIJOFS_BUTTON(51),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
241  { NULL,DIJOFS_BUTTON(52),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
242  { NULL,DIJOFS_BUTTON(53),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
243  { NULL,DIJOFS_BUTTON(54),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
244  { NULL,DIJOFS_BUTTON(55),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
245  { NULL,DIJOFS_BUTTON(56),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
246  { NULL,DIJOFS_BUTTON(57),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
247  { NULL,DIJOFS_BUTTON(58),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
248  { NULL,DIJOFS_BUTTON(59),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
249  { NULL,DIJOFS_BUTTON(60),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
250  { NULL,DIJOFS_BUTTON(61),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
251  { NULL,DIJOFS_BUTTON(62),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
252  { NULL,DIJOFS_BUTTON(63),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
253  { NULL,DIJOFS_BUTTON(64),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
254  { NULL,DIJOFS_BUTTON(65),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
255  { NULL,DIJOFS_BUTTON(66),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
256  { NULL,DIJOFS_BUTTON(67),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
257  { NULL,DIJOFS_BUTTON(68),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
258  { NULL,DIJOFS_BUTTON(69),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
259  { NULL,DIJOFS_BUTTON(70),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
260  { NULL,DIJOFS_BUTTON(71),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
261  { NULL,DIJOFS_BUTTON(72),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
262  { NULL,DIJOFS_BUTTON(73),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
263  { NULL,DIJOFS_BUTTON(74),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
264  { NULL,DIJOFS_BUTTON(75),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
265  { NULL,DIJOFS_BUTTON(76),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
266  { NULL,DIJOFS_BUTTON(77),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
267  { NULL,DIJOFS_BUTTON(78),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
268  { NULL,DIJOFS_BUTTON(79),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
269  { NULL,DIJOFS_BUTTON(80),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
270  { NULL,DIJOFS_BUTTON(81),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
271  { NULL,DIJOFS_BUTTON(82),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
272  { NULL,DIJOFS_BUTTON(83),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
273  { NULL,DIJOFS_BUTTON(84),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
274  { NULL,DIJOFS_BUTTON(85),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
275  { NULL,DIJOFS_BUTTON(86),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
276  { NULL,DIJOFS_BUTTON(87),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
277  { NULL,DIJOFS_BUTTON(88),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
278  { NULL,DIJOFS_BUTTON(89),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
279  { NULL,DIJOFS_BUTTON(90),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
280  { NULL,DIJOFS_BUTTON(91),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
281  { NULL,DIJOFS_BUTTON(92),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
282  { NULL,DIJOFS_BUTTON(93),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
283  { NULL,DIJOFS_BUTTON(94),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
284  { NULL,DIJOFS_BUTTON(95),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
285  { NULL,DIJOFS_BUTTON(96),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
286  { NULL,DIJOFS_BUTTON(97),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
287  { NULL,DIJOFS_BUTTON(98),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
288  { NULL,DIJOFS_BUTTON(99),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
289  { NULL,DIJOFS_BUTTON(100),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
290  { NULL,DIJOFS_BUTTON(101),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
291  { NULL,DIJOFS_BUTTON(102),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
292  { NULL,DIJOFS_BUTTON(103),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
293  { NULL,DIJOFS_BUTTON(104),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
294  { NULL,DIJOFS_BUTTON(105),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
295  { NULL,DIJOFS_BUTTON(106),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
296  { NULL,DIJOFS_BUTTON(107),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
297  { NULL,DIJOFS_BUTTON(108),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
298  { NULL,DIJOFS_BUTTON(109),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
299  { NULL,DIJOFS_BUTTON(110),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
300  { NULL,DIJOFS_BUTTON(111),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
301  { NULL,DIJOFS_BUTTON(112),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
302  { NULL,DIJOFS_BUTTON(113),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
303  { NULL,DIJOFS_BUTTON(114),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
304  { NULL,DIJOFS_BUTTON(115),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
305  { NULL,DIJOFS_BUTTON(116),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
306  { NULL,DIJOFS_BUTTON(117),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
307  { NULL,DIJOFS_BUTTON(118),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
308  { NULL,DIJOFS_BUTTON(119),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
309  { NULL,DIJOFS_BUTTON(120),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
310  { NULL,DIJOFS_BUTTON(121),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
311  { NULL,DIJOFS_BUTTON(122),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
312  { NULL,DIJOFS_BUTTON(123),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
313  { NULL,DIJOFS_BUTTON(124),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
314  { NULL,DIJOFS_BUTTON(125),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
315  { NULL,DIJOFS_BUTTON(126),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
316  { NULL,DIJOFS_BUTTON(127),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
317  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lVX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
318  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lVY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
319  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lVZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
320  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lVRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
321  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lVRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
322  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lVRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
323  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
324  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
325  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lAX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
326  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lAY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
327  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lAZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
328  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lARx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
329  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lARy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
330  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lARz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
331  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
332  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
333  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lFX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
334  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lFY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
335  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lFZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
336  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lFRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
337  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lFRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
338  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lFRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
339  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
340  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
341 };
342 
343 const DIDATAFORMAT c_dfDIJoystick2 = {
344  sizeof(DIDATAFORMAT),
345  sizeof(DIOBJECTDATAFORMAT),
346  DIDF_ABSAXIS,
347  sizeof(DIJOYSTATE2),
348  SDL_arraysize(dfDIJoystick2),
349  dfDIJoystick2
350 };
351 
352 
353 /* Convert a DirectInput return code to a text message */
354 static int
355 SetDIerror(const char *function, HRESULT code)
356 {
357  /*
358  return SDL_SetError("%s() [%s]: %s", function,
359  DXGetErrorString9A(code), DXGetErrorDescription9A(code));
360  */
361  return SDL_SetError("%s() DirectX error %d", function, code);
362 }
363 
364 
365 #define SAFE_RELEASE(p) \
366 { \
367  if (p) { \
368  (p)->lpVtbl->Release((p)); \
369  (p) = 0; \
370  } \
371 }
372 
373 DEFINE_GUID(IID_ValveStreamingGamepad, MAKELONG( 0x28DE, 0x11FF ),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
374 DEFINE_GUID(IID_X360WiredGamepad, MAKELONG( 0x045E, 0x02A1 ),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
375 DEFINE_GUID(IID_X360WirelessGamepad, MAKELONG( 0x045E, 0x028E ),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
376 
377 static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
378 static UINT SDL_RawDevListCount = 0;
379 
380 static SDL_bool
381 SDL_IsXInputDevice( const GUID* pGuidProductFromDirectInput )
382 {
383  static const GUID *s_XInputProductGUID[] = {
384  &IID_ValveStreamingGamepad,
385  &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
386  &IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
387  };
388 
389  size_t iDevice;
390  SDL_bool retval = SDL_FALSE;
391  UINT i;
392 
393  if (!s_bXInputEnabled) {
394  return SDL_FALSE;
395  }
396 
397  /* Check for well known XInput device GUIDs */
398  /* 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. */
399  for ( iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice ) {
400  if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
401  return SDL_TRUE;
402  }
403  }
404 
405  /* Go through RAWINPUT (WinXP and later) to find HID devices. */
406  /* Cache this if we end up using it. */
407  if (SDL_RawDevList == NULL) {
408  if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
409  return SDL_FALSE; /* oh well. */
410  }
411 
412  SDL_RawDevList = (PRAWINPUTDEVICELIST) SDL_malloc(sizeof (RAWINPUTDEVICELIST) * SDL_RawDevListCount);
413  if (SDL_RawDevList == NULL) {
414  SDL_OutOfMemory();
415  return SDL_FALSE;
416  }
417 
418  if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) {
419  SDL_free(SDL_RawDevList);
420  SDL_RawDevList = NULL;
421  return SDL_FALSE; /* oh well. */
422  }
423  }
424 
425  for (i = 0; i < SDL_RawDevListCount; i++) {
426  RID_DEVICE_INFO rdi;
427  char devName[128];
428  UINT rdiSize = sizeof (rdi);
429  UINT nameSize = SDL_arraysize(devName);
430 
431  rdi.cbSize = sizeof (rdi);
432  if ( (SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
433  (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
434  (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
435  (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
436  (SDL_strstr(devName, "IG_") != NULL) ) {
437  return SDL_TRUE;
438  }
439  }
440 
441  return SDL_FALSE;
442 }
443 
444 
445 static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
446 
447 /* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal
448  */
449 LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
450  switch (message) {
451  case WM_DEVICECHANGE:
452  switch (wParam) {
453  case DBT_DEVICEARRIVAL:
454  if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
455  s_bWindowsDeviceChanged = SDL_TRUE;
456  }
457  break;
458  case DBT_DEVICEREMOVECOMPLETE:
459  if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
460  s_bWindowsDeviceChanged = SDL_TRUE;
461  }
462  break;
463  }
464  return 0;
465  }
466 
467  return DefWindowProc (hwnd, message, wParam, lParam);
468 }
469 
470 
471 DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
472  0xC0, 0x4F, 0xB9, 0x51, 0xED);
473 
474 /* Function/thread to scan the system for joysticks.
475  */
476 static int
477 SDL_JoystickThread(void *_data)
478 {
479  HWND messageWindow = 0;
480  HDEVNOTIFY hNotify = 0;
481  DEV_BROADCAST_DEVICEINTERFACE dbh;
482  SDL_bool bOpenedXInputDevices[SDL_XINPUT_MAX_DEVICES];
483  WNDCLASSEX wincl;
484 
485  SDL_zero(bOpenedXInputDevices);
486 
488 
489  SDL_memset( &wincl, 0x0, sizeof(wincl) );
490  wincl.hInstance = GetModuleHandle( NULL );
491  wincl.lpszClassName = L"Message";
492  wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; /* This function is called by windows */
493  wincl.cbSize = sizeof (WNDCLASSEX);
494 
495  if (!RegisterClassEx (&wincl))
496  {
497  return SDL_SetError("Failed to create register class for joystick autodetect.", GetLastError());
498  }
499 
500  messageWindow = (HWND)CreateWindowEx( 0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
501  if ( !messageWindow )
502  {
503  return SDL_SetError("Failed to create message window for joystick autodetect.", GetLastError());
504  }
505 
506  SDL_zero(dbh);
507 
508  dbh.dbcc_size = sizeof(dbh);
509  dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
510  dbh.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
511 
512  hNotify = RegisterDeviceNotification( messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE );
513  if ( !hNotify )
514  {
515  return SDL_SetError("Failed to create notify device for joystick autodetect.", GetLastError());
516  }
517 
518  SDL_LockMutex( s_mutexJoyStickEnum );
519  while ( s_bJoystickThreadQuit == SDL_FALSE )
520  {
521  MSG messages;
522  SDL_bool bXInputChanged = SDL_FALSE;
523 
524  SDL_CondWaitTimeout( s_condJoystickThread, s_mutexJoyStickEnum, 300 );
525 
526  while ( s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE) )
527  {
528  if ( GetMessage(&messages, messageWindow, 0, 0) != 0 ) {
529  TranslateMessage(&messages);
530  DispatchMessage(&messages);
531  }
532  }
533 
534  if ( s_bXInputEnabled && XINPUTGETCAPABILITIES ) {
535  /* scan for any change in XInput devices */
536  Uint8 userId;
537  for (userId = 0; userId < SDL_XINPUT_MAX_DEVICES; userId++) {
538  XINPUT_CAPABILITIES capabilities;
539  const DWORD result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
540  const SDL_bool available = (result == ERROR_SUCCESS);
541  if (bOpenedXInputDevices[userId] != available) {
542  bXInputChanged = SDL_TRUE;
543  bOpenedXInputDevices[userId] = available;
544  }
545  }
546  }
547 
548  if (s_bWindowsDeviceChanged || bXInputChanged) {
549  SDL_UnlockMutex( s_mutexJoyStickEnum ); /* let main thread go while we SDL_Delay(). */
550  SDL_Delay( 300 ); /* wait for direct input to find out about this device */
551  SDL_LockMutex( s_mutexJoyStickEnum );
552 
553  s_bDeviceRemoved = SDL_TRUE;
554  s_bDeviceAdded = SDL_TRUE;
555  s_bWindowsDeviceChanged = SDL_FALSE;
556  }
557  }
558  SDL_UnlockMutex( s_mutexJoyStickEnum );
559 
560  if ( hNotify )
561  UnregisterDeviceNotification( hNotify );
562 
563  if ( messageWindow )
564  DestroyWindow( messageWindow );
565 
566  UnregisterClass( wincl.lpszClassName, wincl.hInstance );
567  messageWindow = 0;
569  return 1;
570 }
571 
572 
573 /* Function to scan the system for joysticks.
574  * This function should set SDL_numjoysticks to the number of available
575  * joysticks. Joystick 0 should be the system default joystick.
576  * It should return 0, or -1 on an unrecoverable fatal error.
577  */
578 int
580 {
581  HRESULT result;
582  HINSTANCE instance;
583  const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
584  if (env && !SDL_atoi(env)) {
585  s_bXInputEnabled = SDL_FALSE;
586  }
587 
588  result = WIN_CoInitialize();
589  if (FAILED(result)) {
590  return SetDIerror("CoInitialize", result);
591  }
592 
593  coinitialized = SDL_TRUE;
594 
595  result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
596  &IID_IDirectInput8, (LPVOID)&dinput);
597 
598  if (FAILED(result)) {
600  return SetDIerror("CoCreateInstance", result);
601  }
602 
603  /* Because we used CoCreateInstance, we need to Initialize it, first. */
604  instance = GetModuleHandle(NULL);
605  if (instance == NULL) {
607  return SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError());
608  }
609  result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
610 
611  if (FAILED(result)) {
613  return SetDIerror("IDirectInput::Initialize", result);
614  }
615 
616  if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
617  s_bXInputEnabled = SDL_FALSE; /* oh well. */
618  }
619 
620  s_mutexJoyStickEnum = SDL_CreateMutex();
621  s_condJoystickThread = SDL_CreateCond();
622  s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
623 
625 
626  if ( !s_threadJoystick )
627  {
628  s_bJoystickThreadQuit = SDL_FALSE;
629  /* spin up the thread to detect hotplug of devices */
630 #if defined(__WIN32__) && !defined(HAVE_LIBC)
631 #undef SDL_CreateThread
632  s_threadJoystick= SDL_CreateThread( SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL );
633 #else
634  s_threadJoystick = SDL_CreateThread( SDL_JoystickThread, "SDL_joystick", NULL );
635 #endif
636  }
637  return SDL_SYS_NumJoysticks();
638 }
639 
640 /* return the number of joysticks that are connected right now */
642 {
643  int nJoysticks = 0;
644  JoyStick_DeviceData *device = SYS_Joystick;
645  while ( device )
646  {
647  nJoysticks++;
648  device = device->pNext;
649  }
650 
651  return nJoysticks;
652 }
653 
654 /* helper function for direct input, gets called for each connected joystick */
655 static BOOL CALLBACK
656  EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
657 {
658  JoyStick_DeviceData *pNewJoystick;
659  JoyStick_DeviceData *pPrevJoystick = NULL;
660 
661  if (SDL_IsXInputDevice( &pdidInstance->guidProduct )) {
662  return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
663  }
664 
665  pNewJoystick = *(JoyStick_DeviceData **)pContext;
666  while ( pNewJoystick )
667  {
668  if ( !SDL_memcmp( &pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance) ) )
669  {
670  /* if we are replacing the front of the list then update it */
671  if ( pNewJoystick == *(JoyStick_DeviceData **)pContext )
672  {
673  *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
674  }
675  else if ( pPrevJoystick )
676  {
677  pPrevJoystick->pNext = pNewJoystick->pNext;
678  }
679 
680  pNewJoystick->pNext = SYS_Joystick;
681  SYS_Joystick = pNewJoystick;
682 
683  return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
684  }
685 
686  pPrevJoystick = pNewJoystick;
687  pNewJoystick = pNewJoystick->pNext;
688  }
689 
690  pNewJoystick = (JoyStick_DeviceData *)SDL_malloc( sizeof(JoyStick_DeviceData) );
691  if (!pNewJoystick) {
692  return DIENUM_CONTINUE; /* better luck next time? */
693  }
694 
695  SDL_zerop(pNewJoystick);
696  pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
697  if (!pNewJoystick->joystickname) {
698  SDL_free(pNewJoystick);
699  return DIENUM_CONTINUE; /* better luck next time? */
700  }
701 
702  SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
703  sizeof(DIDEVICEINSTANCE));
704 
705  pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
706  pNewJoystick->send_add_event = 1;
707  pNewJoystick->nInstanceID = ++s_nInstanceID;
708  SDL_memcpy( &pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid) );
709  pNewJoystick->pNext = SYS_Joystick;
710  SYS_Joystick = pNewJoystick;
711 
712  s_bDeviceAdded = SDL_TRUE;
713 
714  return DIENUM_CONTINUE; /* get next device, please */
715 }
716 
717 static void
718 AddXInputDevice(const Uint8 userid, JoyStick_DeviceData **pContext)
719 {
720  char name[32];
721  JoyStick_DeviceData *pPrevJoystick = NULL;
722  JoyStick_DeviceData *pNewJoystick = *pContext;
723 
724  while (pNewJoystick) {
725  if ((pNewJoystick->bXInputDevice) && (pNewJoystick->XInputUserId == userid)) {
726  /* if we are replacing the front of the list then update it */
727  if (pNewJoystick == *pContext) {
728  *pContext = pNewJoystick->pNext;
729  } else if (pPrevJoystick) {
730  pPrevJoystick->pNext = pNewJoystick->pNext;
731  }
732 
733  pNewJoystick->pNext = SYS_Joystick;
734  SYS_Joystick = pNewJoystick;
735  return; /* already in the list. */
736  }
737 
738  pPrevJoystick = pNewJoystick;
739  pNewJoystick = pNewJoystick->pNext;
740  }
741 
742  pNewJoystick = (JoyStick_DeviceData *) SDL_malloc(sizeof (JoyStick_DeviceData));
743  if (!pNewJoystick) {
744  return; /* better luck next time? */
745  }
746  SDL_zerop(pNewJoystick);
747 
748  SDL_snprintf(name, sizeof (name), "XInput Controller #%u", ((unsigned int) userid) + 1);
749  pNewJoystick->joystickname = SDL_strdup(name);
750  if (!pNewJoystick->joystickname) {
751  SDL_free(pNewJoystick);
752  return; /* better luck next time? */
753  }
754 
755  pNewJoystick->bXInputDevice = SDL_TRUE;
756  pNewJoystick->XInputUserId = userid;
757  pNewJoystick->send_add_event = 1;
758  pNewJoystick->nInstanceID = ++s_nInstanceID;
759  pNewJoystick->pNext = SYS_Joystick;
760  SYS_Joystick = pNewJoystick;
761 
762  s_bDeviceAdded = SDL_TRUE;
763 }
764 
765 static void
766 EnumXInputDevices(JoyStick_DeviceData **pContext)
767 {
768  if (s_bXInputEnabled) {
769  int iuserid;
770  /* iterate in reverse, so these are in the final list in ascending numeric order. */
771  for (iuserid = SDL_XINPUT_MAX_DEVICES-1; iuserid >= 0; iuserid--) {
772  const Uint8 userid = (Uint8) iuserid;
773  XINPUT_CAPABILITIES capabilities;
774  if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
775  /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
776  /* !!! FIXME: we might want to support steering wheels or guitars or whatever laster. */
777  if (capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD) {
778  AddXInputDevice(userid, pContext);
779  }
780  }
781  }
782  }
783 }
784 
785 
786 /* detect any new joysticks being inserted into the system */
788 {
789  JoyStick_DeviceData *pCurList = NULL;
790  /* only enum the devices if the joystick thread told us something changed */
791  if ( s_bDeviceAdded || s_bDeviceRemoved )
792  {
793  SDL_LockMutex( s_mutexJoyStickEnum );
794 
795  s_bDeviceAdded = SDL_FALSE;
796  s_bDeviceRemoved = SDL_FALSE;
797 
798  pCurList = SYS_Joystick;
799  SYS_Joystick = NULL;
800 
801  /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
802  IDirectInput8_EnumDevices(dinput,
803  DI8DEVCLASS_GAMECTRL,
804  EnumJoysticksCallback,
805  &pCurList, DIEDFL_ATTACHEDONLY);
806 
807  SDL_free(SDL_RawDevList); /* in case we used this in DirectInput enumerator. */
808  SDL_RawDevList = NULL;
809  SDL_RawDevListCount = 0;
810 
811  /* Look for XInput devices. Do this last, so they're first in the final list. */
812  EnumXInputDevices(&pCurList);
813 
814  SDL_UnlockMutex( s_mutexJoyStickEnum );
815  }
816 
817  if ( pCurList )
818  {
819  while ( pCurList )
820  {
821  JoyStick_DeviceData *pListNext = NULL;
822 #if !SDL_EVENTS_DISABLED
824  event.type = SDL_JOYDEVICEREMOVED;
825 
826  if (SDL_GetEventState(event.type) == SDL_ENABLE) {
827  event.jdevice.which = pCurList->nInstanceID;
828  if ((SDL_EventOK == NULL)
829  || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
830  SDL_PushEvent(&event);
831  }
832  }
833 #endif /* !SDL_EVENTS_DISABLED */
834 
835  pListNext = pCurList->pNext;
836  SDL_free(pCurList->joystickname);
837  SDL_free(pCurList);
838  pCurList = pListNext;
839  }
840 
841  }
842 
843  if ( s_bDeviceAdded )
844  {
845  JoyStick_DeviceData *pNewJoystick;
846  int device_index = 0;
847  s_bDeviceAdded = SDL_FALSE;
848  pNewJoystick = SYS_Joystick;
849  while ( pNewJoystick )
850  {
851  if ( pNewJoystick->send_add_event )
852  {
853 #if !SDL_EVENTS_DISABLED
855  event.type = SDL_JOYDEVICEADDED;
856 
857  if (SDL_GetEventState(event.type) == SDL_ENABLE) {
858  event.jdevice.which = device_index;
859  if ((SDL_EventOK == NULL)
860  || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
861  SDL_PushEvent(&event);
862  }
863  }
864 #endif /* !SDL_EVENTS_DISABLED */
865  pNewJoystick->send_add_event = 0;
866  }
867  device_index++;
868  pNewJoystick = pNewJoystick->pNext;
869  }
870  }
871 }
872 
873 /* we need to poll if we have pending hotplug device changes or connected devices */
875 {
876  /* we have a new device or one was pulled, we need to think this frame please */
877  if ( s_bDeviceAdded || s_bDeviceRemoved )
878  return SDL_TRUE;
879 
880  return SDL_FALSE;
881 }
882 
883 /* Function to get the device-dependent name of a joystick */
884 const char *
885 SDL_SYS_JoystickNameForDeviceIndex(int device_index)
886 {
887  JoyStick_DeviceData *device = SYS_Joystick;
888 
889  for (; device_index > 0; device_index--)
890  device = device->pNext;
891 
892  return device->joystickname;
893 }
894 
895 /* Function to perform the mapping between current device instance and this joysticks instance id */
897 {
898  JoyStick_DeviceData *device = SYS_Joystick;
899  int index;
900 
901  for (index = device_index; index > 0; index--)
902  device = device->pNext;
903 
904  return device->nInstanceID;
905 }
906 
907 /* Function to open a joystick for use.
908  The joystick to open is specified by the index field of the joystick.
909  This should fill the nbuttons and naxes fields of the joystick structure.
910  It returns 0, or -1 if there is an error.
911  */
912 int
913 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
914 {
915  HRESULT result;
916  JoyStick_DeviceData *joystickdevice = SYS_Joystick;
917 
918  for (; device_index > 0; device_index--)
919  joystickdevice = joystickdevice->pNext;
920 
921  /* allocate memory for system specific hardware data */
922  joystick->instance_id = joystickdevice->nInstanceID;
923  joystick->closed = 0;
924  joystick->hwdata =
925  (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
926  if (joystick->hwdata == NULL) {
927  return SDL_OutOfMemory();
928  }
929  SDL_zerop(joystick->hwdata);
930 
931  if (joystickdevice->bXInputDevice) {
932  const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
933  const Uint8 userId = joystickdevice->XInputUserId;
934  XINPUT_CAPABILITIES capabilities;
935 
936  SDL_assert(s_bXInputEnabled);
938  SDL_assert(userId >= 0);
939  SDL_assert(userId < SDL_XINPUT_MAX_DEVICES);
940 
941  joystick->hwdata->bXInputDevice = SDL_TRUE;
942 
943  if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
944  SDL_free(joystick->hwdata);
945  joystick->hwdata = NULL;
946  return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
947  } else {
948  /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
949  SDL_assert(capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
950  if ((!bIs14OrLater) || (capabilities.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
951  joystick->hwdata->bXInputHaptic = SDL_TRUE;
952  }
953  joystick->hwdata->userid = userId;
954 
955  /* The XInput API has a hard coded button/axis mapping, so we just match it */
956  joystick->naxes = 6;
957  joystick->nbuttons = 15;
958  joystick->nballs = 0;
959  joystick->nhats = 0;
960  }
961  } else { /* use DirectInput, not XInput. */
962  LPDIRECTINPUTDEVICE8 device;
963  DIPROPDWORD dipdw;
964 
965  joystick->hwdata->buffered = 1;
966  joystick->hwdata->removed = 0;
967  joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
968  joystick->hwdata->guid = joystickdevice->guid;
969 
970  SDL_zero(dipdw);
971  dipdw.diph.dwSize = sizeof(DIPROPDWORD);
972  dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
973 
974  result =
975  IDirectInput8_CreateDevice(dinput,
976  &(joystickdevice->dxdevice.guidInstance), &device, NULL);
977  if (FAILED(result)) {
978  return SetDIerror("IDirectInput::CreateDevice", result);
979  }
980 
981  /* Now get the IDirectInputDevice8 interface, instead. */
982  result = IDirectInputDevice8_QueryInterface(device,
983  &IID_IDirectInputDevice8,
984  (LPVOID *) & joystick->
985  hwdata->InputDevice);
986  /* We are done with this object. Use the stored one from now on. */
987  IDirectInputDevice8_Release(device);
988 
989  if (FAILED(result)) {
990  return SetDIerror("IDirectInputDevice8::QueryInterface", result);
991  }
992 
993  /* Acquire shared access. Exclusive access is required for forces,
994  * though. */
995  result =
996  IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
997  InputDevice, SDL_HelperWindow,
998  DISCL_NONEXCLUSIVE |
999  DISCL_BACKGROUND);
1000  if (FAILED(result)) {
1001  return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
1002  }
1003 
1004  /* Use the extended data structure: DIJOYSTATE2. */
1005  result =
1006  IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
1007  &c_dfDIJoystick2);
1008  if (FAILED(result)) {
1009  return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
1010  }
1011 
1012  /* Get device capabilities */
1013  result =
1014  IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
1015  &joystick->hwdata->Capabilities);
1016 
1017  if (FAILED(result)) {
1018  return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
1019  }
1020 
1021  /* Force capable? */
1022  if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
1023 
1024  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1025 
1026  if (FAILED(result)) {
1027  return SetDIerror("IDirectInputDevice8::Acquire", result);
1028  }
1029 
1030  /* reset all accuators. */
1031  result =
1032  IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
1033  InputDevice,
1034  DISFFC_RESET);
1035 
1036  /* Not necessarily supported, ignore if not supported.
1037  if (FAILED(result)) {
1038  return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
1039  }
1040  */
1041 
1042  result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
1043 
1044  if (FAILED(result)) {
1045  return SetDIerror("IDirectInputDevice8::Unacquire", result);
1046  }
1047 
1048  /* Turn on auto-centering for a ForceFeedback device (until told
1049  * otherwise). */
1050  dipdw.diph.dwObj = 0;
1051  dipdw.diph.dwHow = DIPH_DEVICE;
1052  dipdw.dwData = DIPROPAUTOCENTER_ON;
1053 
1054  result =
1055  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
1056  DIPROP_AUTOCENTER, &dipdw.diph);
1057 
1058  /* Not necessarily supported, ignore if not supported.
1059  if (FAILED(result)) {
1060  return SetDIerror("IDirectInputDevice8::SetProperty", result);
1061  }
1062  */
1063  }
1064 
1065  /* What buttons and axes does it have? */
1066  IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
1067  EnumDevObjectsCallback, joystick,
1068  DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
1069 
1070  /* Reorder the input objects. Some devices do not report the X axis as
1071  * the first axis, for example. */
1072  SortDevObjects(joystick);
1073 
1074  dipdw.diph.dwObj = 0;
1075  dipdw.diph.dwHow = DIPH_DEVICE;
1076  dipdw.dwData = INPUT_QSIZE;
1077 
1078  /* Set the buffer size */
1079  result =
1080  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
1081  DIPROP_BUFFERSIZE, &dipdw.diph);
1082 
1083  if (result == DI_POLLEDDEVICE) {
1084  /* This device doesn't support buffering, so we're forced
1085  * to use less reliable polling. */
1086  joystick->hwdata->buffered = 0;
1087  } else if (FAILED(result)) {
1088  return SetDIerror("IDirectInputDevice8::SetProperty", result);
1089  }
1090  }
1091  return (0);
1092 }
1093 
1094 /* return true if this joystick is plugged in right now */
1096 {
1097  return joystick->closed == 0 && joystick->hwdata->removed == 0;
1098 }
1099 
1100 
1101 /* Sort using the data offset into the DInput struct.
1102  * This gives a reasonable ordering for the inputs. */
1103 static int
1104 SortDevFunc(const void *a, const void *b)
1105 {
1106  const input_t *inputA = (const input_t*)a;
1107  const input_t *inputB = (const input_t*)b;
1108 
1109  if (inputA->ofs < inputB->ofs)
1110  return -1;
1111  if (inputA->ofs > inputB->ofs)
1112  return 1;
1113  return 0;
1114 }
1115 
1116 /* Sort the input objects and recalculate the indices for each input. */
1117 static void
1118 SortDevObjects(SDL_Joystick *joystick)
1119 {
1120  input_t *inputs = joystick->hwdata->Inputs;
1121  int nButtons = 0;
1122  int nHats = 0;
1123  int nAxis = 0;
1124  int n;
1125 
1126  SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
1127 
1128  for (n = 0; n < joystick->hwdata->NumInputs; n++)
1129  {
1130  switch (inputs[n].type)
1131  {
1132  case BUTTON:
1133  inputs[n].num = nButtons;
1134  nButtons++;
1135  break;
1136 
1137  case HAT:
1138  inputs[n].num = nHats;
1139  nHats++;
1140  break;
1141 
1142  case AXIS:
1143  inputs[n].num = nAxis;
1144  nAxis++;
1145  break;
1146  }
1147  }
1148 }
1149 
1150 static BOOL CALLBACK
1151 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
1152 {
1153  SDL_Joystick *joystick = (SDL_Joystick *) pvRef;
1154  HRESULT result;
1155  input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
1156 
1157  if (dev->dwType & DIDFT_BUTTON) {
1158  in->type = BUTTON;
1159  in->num = joystick->nbuttons;
1160  in->ofs = DIJOFS_BUTTON( in->num );
1161  joystick->nbuttons++;
1162  } else if (dev->dwType & DIDFT_POV) {
1163  in->type = HAT;
1164  in->num = joystick->nhats;
1165  in->ofs = DIJOFS_POV( in->num );
1166  joystick->nhats++;
1167  } else if (dev->dwType & DIDFT_AXIS) {
1168  DIPROPRANGE diprg;
1169  DIPROPDWORD dilong;
1170 
1171  in->type = AXIS;
1172  in->num = joystick->naxes;
1173  /* work our the axis this guy maps too, thanks for the code icculus! */
1174  if ( !SDL_memcmp( &dev->guidType, &GUID_XAxis, sizeof(dev->guidType) ) )
1175  in->ofs = DIJOFS_X;
1176  else if ( !SDL_memcmp( &dev->guidType, &GUID_YAxis, sizeof(dev->guidType) ) )
1177  in->ofs = DIJOFS_Y;
1178  else if ( !SDL_memcmp( &dev->guidType, &GUID_ZAxis, sizeof(dev->guidType) ) )
1179  in->ofs = DIJOFS_Z;
1180  else if ( !SDL_memcmp( &dev->guidType, &GUID_RxAxis, sizeof(dev->guidType) ) )
1181  in->ofs = DIJOFS_RX;
1182  else if ( !SDL_memcmp( &dev->guidType, &GUID_RyAxis, sizeof(dev->guidType) ) )
1183  in->ofs = DIJOFS_RY;
1184  else if ( !SDL_memcmp( &dev->guidType, &GUID_RzAxis, sizeof(dev->guidType) ) )
1185  in->ofs = DIJOFS_RZ;
1186  else if ( !SDL_memcmp( &dev->guidType, &GUID_Slider, sizeof(dev->guidType) ) )
1187  {
1188  in->ofs = DIJOFS_SLIDER( joystick->hwdata->NumSliders );
1189  ++joystick->hwdata->NumSliders;
1190  }
1191  else
1192  {
1193  return DIENUM_CONTINUE; /* not an axis we can grok */
1194  }
1195 
1196  diprg.diph.dwSize = sizeof(diprg);
1197  diprg.diph.dwHeaderSize = sizeof(diprg.diph);
1198  diprg.diph.dwObj = dev->dwType;
1199  diprg.diph.dwHow = DIPH_BYID;
1200  diprg.lMin = AXIS_MIN;
1201  diprg.lMax = AXIS_MAX;
1202 
1203  result =
1204  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
1205  DIPROP_RANGE, &diprg.diph);
1206  if (FAILED(result)) {
1207  return DIENUM_CONTINUE; /* don't use this axis */
1208  }
1209 
1210  /* Set dead zone to 0. */
1211  dilong.diph.dwSize = sizeof(dilong);
1212  dilong.diph.dwHeaderSize = sizeof(dilong.diph);
1213  dilong.diph.dwObj = dev->dwType;
1214  dilong.diph.dwHow = DIPH_BYID;
1215  dilong.dwData = 0;
1216  result =
1217  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
1218  DIPROP_DEADZONE, &dilong.diph);
1219  if (FAILED(result)) {
1220  return DIENUM_CONTINUE; /* don't use this axis */
1221  }
1222 
1223  joystick->naxes++;
1224  } else {
1225  /* not supported at this time */
1226  return DIENUM_CONTINUE;
1227  }
1228 
1229  joystick->hwdata->NumInputs++;
1230 
1231  if (joystick->hwdata->NumInputs == MAX_INPUTS) {
1232  return DIENUM_STOP; /* too many */
1233  }
1234 
1235  return DIENUM_CONTINUE;
1236 }
1237 
1238 /* Function to update the state of a joystick - called as a device poll.
1239  * This function shouldn't update the joystick structure directly,
1240  * but instead should call SDL_PrivateJoystick*() to deliver events
1241  * and update joystick device state.
1242  */
1243 void
1244 SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick)
1245 {
1246  DIJOYSTATE2 state;
1247  HRESULT result;
1248  int i;
1249 
1250  result =
1251  IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
1252  sizeof(DIJOYSTATE2), &state);
1253  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1254  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1255  result =
1256  IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
1257  sizeof(DIJOYSTATE2), &state);
1258  }
1259 
1260  if ( result != DI_OK )
1261  {
1262  joystick->hwdata->send_remove_event = 1;
1263  joystick->hwdata->removed = 1;
1264  return;
1265  }
1266 
1267  /* Set each known axis, button and POV. */
1268  for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
1269  const input_t *in = &joystick->hwdata->Inputs[i];
1270 
1271  switch (in->type) {
1272  case AXIS:
1273  switch (in->ofs) {
1274  case DIJOFS_X:
1275  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1276  (Sint16) state.lX);
1277  break;
1278  case DIJOFS_Y:
1279  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1280  (Sint16) state.lY);
1281  break;
1282  case DIJOFS_Z:
1283  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1284  (Sint16) state.lZ);
1285  break;
1286  case DIJOFS_RX:
1287  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1288  (Sint16) state.lRx);
1289  break;
1290  case DIJOFS_RY:
1291  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1292  (Sint16) state.lRy);
1293  break;
1294  case DIJOFS_RZ:
1295  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1296  (Sint16) state.lRz);
1297  break;
1298  case DIJOFS_SLIDER(0):
1299  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1300  (Sint16) state.rglSlider[0]);
1301  break;
1302  case DIJOFS_SLIDER(1):
1303  SDL_PrivateJoystickAxis_Int(joystick, in->num,
1304  (Sint16) state.rglSlider[1]);
1305  break;
1306  }
1307 
1308  break;
1309 
1310  case BUTTON:
1311  SDL_PrivateJoystickButton_Int(joystick, in->num,
1312  (Uint8) (state.
1313  rgbButtons[in->ofs -
1314  DIJOFS_BUTTON0]
1315  ? SDL_PRESSED :
1316  SDL_RELEASED));
1317  break;
1318  case HAT:
1319  {
1320  Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs -
1321  DIJOFS_POV(0)]);
1322  SDL_PrivateJoystickHat_Int(joystick, in->num, pos);
1323  break;
1324  }
1325  }
1326  }
1327 }
1328 
1329 void
1330 SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
1331 {
1332  int i;
1333  HRESULT result;
1334  DWORD numevents;
1335  DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
1336 
1337  numevents = INPUT_QSIZE;
1338  result =
1339  IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
1340  sizeof(DIDEVICEOBJECTDATA), evtbuf,
1341  &numevents, 0);
1342  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1343  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1344  result =
1345  IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
1346  sizeof(DIDEVICEOBJECTDATA),
1347  evtbuf, &numevents, 0);
1348  }
1349 
1350  /* Handle the events or punt */
1351  if (FAILED(result))
1352  {
1353  joystick->hwdata->send_remove_event = 1;
1354  joystick->hwdata->removed = 1;
1355  return;
1356  }
1357 
1358  for (i = 0; i < (int) numevents; ++i) {
1359  int j;
1360 
1361  for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
1362  const input_t *in = &joystick->hwdata->Inputs[j];
1363 
1364  if (evtbuf[i].dwOfs != in->ofs)
1365  continue;
1366 
1367  switch (in->type) {
1368  case AXIS:
1369  SDL_PrivateJoystickAxis(joystick, in->num,
1370  (Sint16) evtbuf[i].dwData);
1371  break;
1372  case BUTTON:
1373  SDL_PrivateJoystickButton(joystick, in->num,
1374  (Uint8) (evtbuf[i].
1375  dwData ? SDL_PRESSED :
1376  SDL_RELEASED));
1377  break;
1378  case HAT:
1379  {
1380  Uint8 pos = TranslatePOV(evtbuf[i].dwData);
1381  SDL_PrivateJoystickHat(joystick, in->num, pos);
1382  }
1383  }
1384  }
1385  }
1386 }
1387 
1388 
1389 /* Function to return > 0 if a bit array of buttons differs after applying a mask
1390 */
1391 int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
1392 {
1393  return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
1394 }
1395 
1396 /* Function to update the state of a XInput style joystick.
1397 */
1398 void
1399 SDL_SYS_JoystickUpdate_XInput(SDL_Joystick * joystick)
1400 {
1401  HRESULT result;
1402 
1403  if ( !XINPUTGETSTATE )
1404  return;
1405 
1406  result = XINPUTGETSTATE( joystick->hwdata->userid, &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot] );
1407  if ( result == ERROR_DEVICE_NOT_CONNECTED )
1408  {
1409  joystick->hwdata->send_remove_event = 1;
1410  joystick->hwdata->removed = 1;
1411  return;
1412  }
1413 
1414  /* only fire events if the data changed from last time */
1415  if ( joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot].dwPacketNumber != 0
1416  && joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot].dwPacketNumber != joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot^1].dwPacketNumber )
1417  {
1418  XINPUT_STATE_EX *pXInputState = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot];
1419  XINPUT_STATE_EX *pXInputStatePrev = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot ^ 1];
1420 
1421  SDL_PrivateJoystickAxis( joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX );
1422  SDL_PrivateJoystickAxis( joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)) );
1423  SDL_PrivateJoystickAxis( joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX );
1424  SDL_PrivateJoystickAxis( joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)) );
1425  SDL_PrivateJoystickAxis( joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger*65535/255) - 32768));
1426  SDL_PrivateJoystickAxis( joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger*65535/255) - 32768));
1427 
1428  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) )
1429  SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED : SDL_RELEASED );
1430  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) )
1431  SDL_PrivateJoystickButton(joystick, 1, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? SDL_PRESSED : SDL_RELEASED );
1432  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_LEFT ) )
1433  SDL_PrivateJoystickButton(joystick, 2, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? SDL_PRESSED : SDL_RELEASED );
1434  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_RIGHT ) )
1435  SDL_PrivateJoystickButton(joystick, 3, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? SDL_PRESSED : SDL_RELEASED );
1436  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_START ) )
1437  SDL_PrivateJoystickButton(joystick, 4, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_START ? SDL_PRESSED : SDL_RELEASED );
1438  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_BACK ) )
1439  SDL_PrivateJoystickButton(joystick, 5, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? SDL_PRESSED : SDL_RELEASED );
1440  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_THUMB ) )
1441  SDL_PrivateJoystickButton(joystick, 6, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? SDL_PRESSED : SDL_RELEASED );
1442  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_THUMB ) )
1443  SDL_PrivateJoystickButton(joystick, 7, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? SDL_PRESSED : SDL_RELEASED );
1444  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_SHOULDER ) )
1445  SDL_PrivateJoystickButton(joystick, 8, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
1446  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER ) )
1447  SDL_PrivateJoystickButton(joystick, 9, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
1448  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_A ) )
1449  SDL_PrivateJoystickButton(joystick, 10, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_A ? SDL_PRESSED : SDL_RELEASED );
1450  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_B ) )
1451  SDL_PrivateJoystickButton(joystick, 11, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_B ? SDL_PRESSED : SDL_RELEASED );
1452  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_X ) )
1453  SDL_PrivateJoystickButton(joystick, 12, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_X ? SDL_PRESSED : SDL_RELEASED );
1454  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_Y ) )
1455  SDL_PrivateJoystickButton(joystick, 13, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_Y ? SDL_PRESSED : SDL_RELEASED );
1456  if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, 0x400 ) )
1457  SDL_PrivateJoystickButton(joystick, 14, pXInputState->Gamepad.wButtons & 0x400 ? SDL_PRESSED : SDL_RELEASED ); /* 0x400 is the undocumented code for the guide button */
1458 
1459  joystick->hwdata->currentXInputSlot ^= 1;
1460 
1461  }
1462 }
1463 
1464 
1465 static Uint8
1466 TranslatePOV(DWORD value)
1467 {
1468  const int HAT_VALS[] = {
1469  SDL_HAT_UP,
1471  SDL_HAT_RIGHT,
1473  SDL_HAT_DOWN,
1474  SDL_HAT_DOWN | SDL_HAT_LEFT,
1475  SDL_HAT_LEFT,
1476  SDL_HAT_UP | SDL_HAT_LEFT
1477  };
1478 
1479  if (LOWORD(value) == 0xFFFF)
1480  return SDL_HAT_CENTERED;
1481 
1482  /* Round the value up: */
1483  value += 4500 / 2;
1484  value %= 36000;
1485  value /= 4500;
1486 
1487  if (value >= 8)
1488  return SDL_HAT_CENTERED; /* shouldn't happen */
1489 
1490  return HAT_VALS[value];
1491 }
1492 
1493 /* SDL_PrivateJoystick* doesn't discard duplicate events, so we need to
1494  * do it. */
1495 static int
1496 SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
1497 {
1498  if (joystick->axes[axis] != value)
1499  return SDL_PrivateJoystickAxis(joystick, axis, value);
1500  return 0;
1501 }
1502 
1503 static int
1504 SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
1505 {
1506  if (joystick->hats[hat] != value)
1507  return SDL_PrivateJoystickHat(joystick, hat, value);
1508  return 0;
1509 }
1510 
1511 static int
1512 SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick, Uint8 button,
1513  Uint8 state)
1514 {
1515  if (joystick->buttons[button] != state)
1516  return SDL_PrivateJoystickButton(joystick, button, state);
1517  return 0;
1518 }
1519 
1520 void
1522 {
1523  HRESULT result;
1524 
1525  if ( joystick->closed || !joystick->hwdata )
1526  return;
1527 
1528  if (joystick->hwdata->bXInputDevice)
1529  {
1530  SDL_SYS_JoystickUpdate_XInput(joystick);
1531  }
1532  else
1533  {
1534  result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
1535  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1536  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1537  IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
1538  }
1539 
1540  if (joystick->hwdata->buffered)
1541  SDL_SYS_JoystickUpdate_Buffered(joystick);
1542  else
1543  SDL_SYS_JoystickUpdate_Polled(joystick);
1544  }
1545 
1546  if ( joystick->hwdata->removed )
1547  {
1548  joystick->closed = 1;
1549  joystick->uncentered = 1;
1550  }
1551 }
1552 
1553 /* Function to close a joystick after use */
1554 void
1556 {
1557  if (!joystick->hwdata->bXInputDevice) {
1558  IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
1559  IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
1560  }
1561 
1562  /* free system specific hardware data */
1563  SDL_free(joystick->hwdata);
1564 
1565  joystick->closed = 1;
1566 }
1567 
1568 /* Function to perform any system-specific joystick related cleanup */
1569 void
1571 {
1572  JoyStick_DeviceData *device = SYS_Joystick;
1573 
1574  while ( device )
1575  {
1576  JoyStick_DeviceData *device_next = device->pNext;
1577  SDL_free(device->joystickname);
1578  SDL_free(device);
1579  device = device_next;
1580  }
1581  SYS_Joystick = NULL;
1582 
1583  if ( s_threadJoystick )
1584  {
1585  SDL_LockMutex( s_mutexJoyStickEnum );
1586  s_bJoystickThreadQuit = SDL_TRUE;
1587  SDL_CondBroadcast( s_condJoystickThread ); /* signal the joystick thread to quit */
1588  SDL_UnlockMutex( s_mutexJoyStickEnum );
1589  SDL_WaitThread( s_threadJoystick, NULL ); /* wait for it to bugger off */
1590 
1591  SDL_DestroyMutex( s_mutexJoyStickEnum );
1592  SDL_DestroyCond( s_condJoystickThread );
1593  s_condJoystickThread= NULL;
1594  s_mutexJoyStickEnum = NULL;
1595  s_threadJoystick = NULL;
1596  }
1597 
1598  if (dinput != NULL) {
1599  IDirectInput8_Release(dinput);
1600  dinput = NULL;
1601  }
1602 
1603  if (coinitialized) {
1605  coinitialized = SDL_FALSE;
1606  }
1607 
1608  if (s_bXInputEnabled) {
1610  }
1611 }
1612 
1613 /* return the stable device guid for this device index */
1615 {
1616  JoyStick_DeviceData *device = SYS_Joystick;
1617  int index;
1618 
1619  for (index = device_index; index > 0; index--)
1620  device = device->pNext;
1621 
1622  return device->guid;
1623 }
1624 
1626 {
1627  return joystick->hwdata->guid;
1628 }
1629 
1630 /* return SDL_TRUE if this device is using XInput */
1631 SDL_bool SDL_SYS_IsXInputDeviceIndex(int device_index)
1632 {
1633  JoyStick_DeviceData *device = SYS_Joystick;
1634  int index;
1635 
1636  for (index = device_index; index > 0; index--)
1637  device = device->pNext;
1638 
1639  return device->bXInputDevice;
1640 }
1641 
1642 /* return SDL_TRUE if this device was opened with XInput */
1643 SDL_bool SDL_SYS_IsXInputJoystick(SDL_Joystick * joystick)
1644 {
1645  return joystick->hwdata->bXInputDevice;
1646 }
1647 
1648 #endif /* SDL_JOYSTICK_DINPUT */
1649 
1650 /* vi: set ts=4 sw=4 expandtab: */
input_t Inputs[MAX_INPUTS]
DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond)
Definition: SDL_syscond.c:64
XINPUT_GAMEPAD_EX Gamepad
#define DIRECTINPUT_VERSION
Definition: directx.h:74
DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
Definition: SDL_syscond.c:160
#define INVALID_XINPUT_USERID
DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event *event)
Add an event to the event queue.
Definition: SDL_events.c:457
SDL_JoystickGUID guid
LPDIRECTINPUTDEVICE8 InputDevice
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2540
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:536
int SDL_SYS_NumJoysticks()
#define NULL
Definition: ftobjs.h:61
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:73
SDL_bool
Definition: SDL_stdinc.h:116
GLclampd n
Definition: glew.h:7287
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:72
DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void)
Definition: SDL_sysmutex.c:38
GLuint in
Definition: glew.h:10672
DECLSPEC void SDLCALL SDL_free(void *mem)
int32_t j
Definition: e_log.c:102
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:610
#define SDL_ENABLE
Definition: SDL_events.h:688
int const char * version
Definition: zlib.h:813
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
EGLImageKHR EGLint * name
Definition: eglext.h:284
DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len)
Definition: SDL_string.c:370
DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond)
Definition: SDL_syscond.c:106
void SDL_SYS_JoystickQuit(void)
#define XINPUT_CAPS_FFB_SUPPORTED
XInputSetState_t SDL_XInputSetState
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
#define XINPUTGETCAPABILITIES
#define SDL_XINPUT_MAX_DEVICES
DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:160
struct joystick_hwdata * hwdata
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:496
DIDEVCAPS Capabilities
#define SDL_HINT_XINPUT_ENABLED
A variable that lets you disable the detection and use of Xinput gamepad devices. ...
Definition: SDL_hints.h:215
DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:399
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:193
GLuint64EXT * result
Definition: glew.h:12708
typedef HANDLE(WINAPI *PFNWGLCREATEBUFFERREGIONARBPROC)(HDC hDC
#define SDL_GetEventState(type)
Definition: SDL_events.h:701
int
Definition: SDL_systhread.c:37
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:195
void WIN_UnloadXInputDLL(void)
HRESULT WIN_CoInitialize(void)
#define MAX_INPUTS
DECLSPEC char *SDLCALL SDL_strdup(const char *str)
Definition: SDL_string.c:511
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
SDL_EventFilter SDL_EventOK
Definition: SDL_events.c:40
DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle)
Definition: SDL_string.c:612
#define SDL_max(x, y)
Definition: SDL_stdinc.h:245
#define XINPUTGETSTATE
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
Definition: SDL_systimer.c:70
static void * pContext
Definition: dsound.c:51
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
void SDL_SYS_JoystickDetect()
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:41
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
GLuint index
Definition: glew.h:1800
DECLSPEC const char *SDLCALL SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void)
Definition: SDL_syscond.c:42
jmp_buf env
Definition: jumphack.c:12
DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data)
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
GLuint num
Definition: glew.h:2631
typedef LPVOID(WINAPI *PFNWGLCREATEIMAGEBUFFERI3DPROC)(HDC hDC
DWORD SDL_XInputVersion
SDL_bool SDL_SYS_JoystickNeedsPolling()
#define SDL_assert(condition)
Definition: SDL_assert.h:159
int SDL_SYS_JoystickInit(void)
void * SDL_EventOKParam
Definition: SDL_events.c:41
Definition: inftrees.h:24
GLuint GLfloat x0
Definition: glew.h:11582
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
void WIN_CoUninitialize(void)
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
struct SDL_mutex SDL_mutex
Definition: SDL_mutex.h:59
int WIN_LoadXInputDLL(void)
EGLSurface EGLint void ** value
Definition: eglext.h:301
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
XInputGetCapabilities_t SDL_XInputGetCapabilities
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
DECLSPEC int SDLCALL SDL_atoi(const char *str)
Definition: SDL_string.c:774
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
#define SDL_zerop(x)
Definition: SDL_stdinc.h:255
int16_t Sint16
A signed 16-bit integer type.
Definition: SDL_stdinc.h:133
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
HVIDEOINPUTDEVICENV hDevice
Definition: wglew.h:1093
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
General event structure.
Definition: SDL_events.h:495
DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int(*compare)(const void *, const void *))
#define SDL_zero(x)
Definition: SDL_stdinc.h:254
DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:61
XInputGetState_t SDL_XInputGetState
#define SDL_PRESSED
Definition: SDL_events.h:50
int i
Definition: pngrutil.c:1377
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:191
XINPUT_STATE_EX XInputState[2]
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_HAT_UP
Definition: SDL_joystick.h:192
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:194
SDL_JoystickID instance_id
typedef VOID(WINAPI *PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)(HGLRC dstCtx
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
Uint32 type
Definition: SDL_events.h:497
cl_event event
Definition: glew.h:3556
typedef BOOL(WINAPI *PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC
struct SDL_cond SDL_cond
Definition: SDL_mutex.h:167