zenilib: zenilib/jni/external/sdl/src/joystick/windows/SDL_dxjoystick.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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;
81 DWORD SDL_XInputVersion = 0;
82
83 static HANDLE s_pXInputDLL = 0;
84 static int s_XInputDLLRefCount = 0;
85
86 int
87 WIN_LoadXInputDLL(void)
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);
111 SDL_XInputVersion = version;
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" );
118 if ( !SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities ) {
119 WIN_UnloadXInputDLL();
120 return -1;
121 }
122
123 return 0;
124 }
125
126 void
127 WIN_UnloadXInputDLL(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
487 WIN_CoInitialize();
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;
568 WIN_CoUninitialize();
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
579 SDL_SYS_JoystickInit(void)
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)) {
599 SDL_SYS_JoystickQuit();
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) {
606 SDL_SYS_JoystickQuit();
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)) {
612 SDL_SYS_JoystickQuit();
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
624 SDL_SYS_JoystickDetect();
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 */
641 int SDL_SYS_NumJoysticks()
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 */
787 void SDL_SYS_JoystickDetect()
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
823 SDL_Event event;
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
854 SDL_Event event;
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 */
874 SDL_bool SDL_SYS_JoystickNeedsPolling()
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 */
896 SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
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);
937 SDL_assert(XINPUTGETCAPABILITIES);
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 */
1095 SDL_bool SDL_SYS_JoystickAttached( SDL_Joystick * joystick )
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,
1470 SDL_HAT_UP | SDL_HAT_RIGHT,
1471 SDL_HAT_RIGHT,
1472 SDL_HAT_DOWN | 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
1521 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
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
1555 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
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
1570 SDL_SYS_JoystickQuit(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) {
1604 WIN_CoUninitialize();
1605 coinitialized = SDL_FALSE;
1606 }
1607
1608 if (s_bXInputEnabled) {
1609 WIN_UnloadXInputDLL();
1610 }
1611 }
1612
1613 /* return the stable device guid for this device index */
1614 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int 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
1625 SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
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: */
joystick_hwdata::Inputs
input_t Inputs[MAX_INPUTS]
Definition: SDL_dxjoystick_c.h:138
SDL_DestroyCond
DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond)
Definition: SDL_syscond.c:64
XINPUT_STATE_EX::Gamepad
XINPUT_GAMEPAD_EX Gamepad
Definition: SDL_dxjoystick_c.h:74
DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION
Definition: directx.h:74
joystick_hwdata::currentXInputSlot
Uint8 currentXInputSlot
Definition: SDL_dxjoystick_c.h:146
SDL_CondWaitTimeout
DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
Definition: SDL_syscond.c:160
INVALID_XINPUT_USERID
#define INVALID_XINPUT_USERID
Definition: SDL_dxjoystick_c.h:108
SDL_PushEvent
DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event *event)
Add an event to the event queue.
Definition: SDL_events.c:457
joystick_hwdata::guid
SDL_JoystickGUID guid
Definition: SDL_sysjoystick_c.h:82
SDL_joystick.h
joystick_hwdata::InputDevice
LPDIRECTINPUTDEVICE8 InputDevice
Definition: SDL_dxjoystick_c.h:133
type
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
XINPUT_STATE_EX::dwPacketNumber
DWORD dwPacketNumber
Definition: SDL_dxjoystick_c.h:73
message
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2540
SDL_PrivateJoystickHat
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:536
SDL_SYS_NumJoysticks
int SDL_SYS_NumJoysticks()
Definition: SDL_sysjoystick.m:43
NULL
#define NULL
Definition: ftobjs.h:61
SDL_snprintf
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
HRESULT
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
SDL_LockMutex
DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:73
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:116
n
GLclampd n
Definition: glew.h:7287
BUTTON
Definition: SDL_dxjoystick_c.h:116
SDL_JOYDEVICEADDED
Definition: SDL_events.h:110
SDL_JoystickID
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:72
SDL_TRUE
Definition: SDL_stdinc.h:119
joystick_hwdata::NumInputs
int NumInputs
Definition: SDL_dxjoystick_c.h:139
_SDL_Joystick::axes
Sint16 * axes
Definition: SDL_sysjoystick.h:35
SDL_CreateMutex
DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void)
Definition: SDL_sysmutex.c:38
SDL_events.h
in
GLuint in
Definition: glew.h:10672
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
AXIS
Definition: SDL_dxjoystick_c.h:116
j
int32_t j
Definition: e_log.c:102
SDL_PrivateJoystickButton
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:610
joystick_hwdata::buffered
int buffered
Definition: SDL_dxjoystick_c.h:135
SDL_ENABLE
#define SDL_ENABLE
Definition: SDL_events.h:688
version
int const char * version
Definition: zlib.h:813
XINPUT_STATE_EX
Definition: SDL_dxjoystick_c.h:71
joystick_hwdata::userid
Uint8 userid
Definition: SDL_dxjoystick_c.h:145
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
joystick_hwdata::removed
int removed
Definition: SDL_sysjoystick_c.h:78
name
EGLImageKHR EGLint * name
Definition: eglext.h:284
SDL_memcmp
DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len)
Definition: SDL_string.c:370
SDL_CondBroadcast
DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond)
Definition: SDL_syscond.c:106
SDL_SYS_JoystickQuit
void SDL_SYS_JoystickQuit(void)
Definition: SDL_sysjoystick.m:129
XINPUT_CAPS_FFB_SUPPORTED
#define XINPUT_CAPS_FFB_SUPPORTED
Definition: SDL_dxjoystick_c.h:54
XINPUT_GAMEPAD_EX::bLeftTrigger
BYTE bLeftTrigger
Definition: SDL_dxjoystick_c.h:62
SDL_XInputSetState
XInputSetState_t SDL_XInputSetState
UINT
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
SDL_FALSE
Definition: SDL_stdinc.h:118
_SDL_Joystick::buttons
Uint8 * buttons
Definition: SDL_sysjoystick.h:47
joystick_hwdata::send_remove_event
Uint8 send_remove_event
Definition: SDL_dxjoystick_c.h:142
XINPUT_GAMEPAD_EX::sThumbRX
SHORT sThumbRX
Definition: SDL_dxjoystick_c.h:66
XINPUTGETCAPABILITIES
#define XINPUTGETCAPABILITIES
Definition: SDL_dxjoystick_c.h:107
XINPUT_GAMEPAD_EX::sThumbLY
SHORT sThumbLY
Definition: SDL_dxjoystick_c.h:65
_SDL_Joystick::hats
Uint8 * hats
Definition: SDL_sysjoystick.h:38
SDL_XINPUT_MAX_DEVICES
#define SDL_XINPUT_MAX_DEVICES
Definition: SDL_dxjoystick_c.h:109
SDL_config.h
SDL_UnlockMutex
DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:160
_SDL_Joystick::hwdata
struct joystick_hwdata * hwdata
Definition: SDL_sysjoystick.h:49
SDL_PrivateJoystickAxis
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:496
_SDL_Joystick::nballs
int nballs
Definition: SDL_sysjoystick.h:40
input_t::ofs
DWORD ofs
Definition: SDL_dxjoystick_c.h:121
joystick_hwdata
Definition: SDL_sysjoystick_c.h:58
joystick_hwdata::Capabilities
DIDEVCAPS Capabilities
Definition: SDL_dxjoystick_c.h:134
SDL_HINT_XINPUT_ENABLED
#define SDL_HINT_XINPUT_ENABLED
A variable that lets you disable the detection and use of Xinput gamepad devices. ...
Definition: SDL_hints.h:215
SDL_JOYDEVICEREMOVED
Definition: SDL_events.h:111
SDL_WaitThread
DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:399
input_t::type
Type type
Definition: SDL_dxjoystick_c.h:124
SDL_HAT_RIGHT
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:193
result
GLuint64EXT * result
Definition: glew.h:12708
HANDLE
typedef HANDLE(WINAPI *PFNWGLCREATEBUFFERREGIONARBPROC)(HDC hDC
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:701
int
int
Definition: SDL_systhread.c:37
input_t::num
Uint8 num
Definition: SDL_dxjoystick_c.h:127
SDL_HAT_LEFT
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:195
WIN_UnloadXInputDLL
void WIN_UnloadXInputDLL(void)
WIN_CoInitialize
HRESULT WIN_CoInitialize(void)
MAX_INPUTS
#define MAX_INPUTS
Definition: SDL_dxjoystick_c.h:111
SDL_strdup
DECLSPEC char *SDLCALL SDL_strdup(const char *str)
Definition: SDL_string.c:511
_SDL_Joystick::uncentered
Uint8 uncentered
Definition: SDL_sysjoystick.h:54
SDL_SYS_JoystickAttached
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:87
SDL_EventOK
SDL_EventFilter SDL_EventOK
Definition: SDL_events.c:40
SDL_strstr
DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle)
Definition: SDL_string.c:612
SDL_max
#define SDL_max(x, y)
Definition: SDL_stdinc.h:245
XINPUTGETSTATE
#define XINPUTGETSTATE
Definition: SDL_dxjoystick_c.h:105
SDL_Delay
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
Definition: SDL_systimer.c:70
pContext
static void * pContext
Definition: dsound.c:51
SDL_memset
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
joystick_hwdata::bXInputDevice
Uint8 bXInputDevice
Definition: SDL_dxjoystick_c.h:143
SDL_hints.h
SDL_SYS_JoystickDetect
void SDL_SYS_JoystickDetect()
Definition: SDL_sysjoystick.m:48
WIN_StringToUTF8
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:41
DEFINE_GUID
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
SDL_SetError
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
SDL_malloc
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_SYS_JoystickNameForDeviceIndex
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
Definition: SDL_sysjoystick.m:59
index
GLuint index
Definition: glew.h:1800
XINPUT_GAMEPAD_EX::wButtons
WORD wButtons
Definition: SDL_dxjoystick_c.h:61
SDL_GetHint
DECLSPEC const char *SDLCALL SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
SDL_SYS_JoystickUpdate
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:98
SDL_CreateCond
DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void)
Definition: SDL_syscond.c:42
env
jmp_buf env
Definition: jumphack.c:12
SDL_CreateThread
DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data)
SDL_SYS_JoystickGetGUID
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:143
num
GLuint num
Definition: glew.h:2631
LPVOID
typedef LPVOID(WINAPI *PFNWGLCREATEIMAGEBUFFERI3DPROC)(HDC hDC
SDL_XInputVersion
DWORD SDL_XInputVersion
XINPUT_GAMEPAD_EX::sThumbRY
SHORT sThumbRY
Definition: SDL_dxjoystick_c.h:67
SDL_SYS_JoystickNeedsPolling
SDL_bool SDL_SYS_JoystickNeedsPolling()
Definition: SDL_sysjoystick.m:52
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:159
SDL_SYS_JoystickInit
int SDL_SYS_JoystickInit(void)
Definition: SDL_sysjoystick.m:38
SDL_EventOKParam
void * SDL_EventOKParam
Definition: SDL_events.c:41
code
Definition: inftrees.h:24
x0
GLuint GLfloat x0
Definition: glew.h:11582
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
joystick_hwdata::bXInputHaptic
Uint8 bXInputHaptic
Definition: SDL_dxjoystick_c.h:144
WIN_CoUninitialize
void WIN_CoUninitialize(void)
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
SDL_mutex
struct SDL_mutex SDL_mutex
Definition: SDL_mutex.h:59
joystick_hwdata::NumSliders
int NumSliders
Definition: SDL_dxjoystick_c.h:140
WIN_LoadXInputDLL
int WIN_LoadXInputDLL(void)
value
EGLSurface EGLint void ** value
Definition: eglext.h:301
SDL_memcpy
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
SDL_XInputGetCapabilities
XInputGetCapabilities_t SDL_XInputGetCapabilities
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
SDL_atoi
DECLSPEC int SDLCALL SDL_atoi(const char *str)
Definition: SDL_string.c:774
DWORD
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
SDL_JoystickGUID
Definition: SDL_joystick.h:68
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:255
Sint16
int16_t Sint16
A signed 16-bit integer type.
Definition: SDL_stdinc.h:133
_SDL_Joystick
Definition: SDL_sysjoystick.h:29
SDL_SYS_GetInstanceIdOfDeviceIndex
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
Definition: SDL_sysjoystick.m:65
b
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
hDevice
HVIDEOINPUTDEVICENV hDevice
Definition: wglew.h:1093
SDL_Thread
Definition: SDL_thread_c.h:48
SDL_SYS_JoystickOpen
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
Definition: SDL_sysjoystick.m:76
SDL_Event
General event structure.
Definition: SDL_events.h:495
HAT
Definition: SDL_dxjoystick_c.h:116
SDL_qsort
DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int(*compare)(const void *, const void *))
_SDL_Joystick::nbuttons
int nbuttons
Definition: SDL_sysjoystick.h:46
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:254
SDL_DestroyMutex
DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:61
SDL_XInputGetState
XInputGetState_t SDL_XInputGetState
_SDL_Joystick::closed
Uint8 closed
Definition: SDL_sysjoystick.h:53
SDL_PRESSED
#define SDL_PRESSED
Definition: SDL_events.h:50
i
int i
Definition: pngrutil.c:1377
SDL_HAT_CENTERED
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:191
joystick_hwdata::XInputState
XINPUT_STATE_EX XInputState[2]
Definition: SDL_dxjoystick_c.h:147
SDL_timer.h
SDL_SYS_JoystickClose
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:119
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_HAT_UP
#define SDL_HAT_UP
Definition: SDL_joystick.h:192
SDL_dxjoystick_c.h
SDL_HAT_DOWN
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:194
SDL_error.h
_SDL_Joystick::naxes
int naxes
Definition: SDL_sysjoystick.h:34
_SDL_Joystick::instance_id
SDL_JoystickID instance_id
Definition: SDL_sysjoystick.h:31
VOID
typedef VOID(WINAPI *PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)(HGLRC dstCtx
SDL_SYS_JoystickGetDeviceGUID
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
Definition: SDL_sysjoystick.m:133
SDL_Event::type
Uint32 type
Definition: SDL_events.h:497
SDL_assert.h
_SDL_Joystick::nhats
int nhats
Definition: SDL_sysjoystick.h:37
event
cl_event event
Definition: glew.h:3556
input_t
Definition: SDL_dxjoystick_c.h:118
XINPUT_GAMEPAD_EX::sThumbLX
SHORT sThumbLX
Definition: SDL_dxjoystick_c.h:64
BOOL
typedef BOOL(WINAPI *PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC
SDL_cond
struct SDL_cond SDL_cond
Definition: SDL_mutex.h:167
XINPUT_GAMEPAD_EX::bRightTrigger
BYTE bRightTrigger
Definition: SDL_dxjoystick_c.h:63