Fixed a bunch of compiler warnings with Cygwin/MingW.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "SDL_config.h"
23 #ifdef SDL_JOYSTICK_DINPUT
25 /* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
26 * A. Formiga's WINMM driver.
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.
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 IDirectInputDevice2_GetDeviceData and
33 * let it return 0 events. */
35 #include "SDL_error.h"
36 #include "SDL_events.h"
37 #include "SDL_joystick.h"
38 #include "../SDL_sysjoystick.h"
39 #include "../SDL_joystick_c.h"
40 #define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
41 #include "SDL_dxjoystick_c.h"
44 #ifndef DIDFT_OPTIONAL
45 #define DIDFT_OPTIONAL 0x80000000
49 #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
50 #define MAX_JOYSTICKS 8
51 #define AXIS_MIN -32768 /* minimum value for axis coordinate */
52 #define AXIS_MAX 32767 /* maximum value for axis coordinate */
53 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
55 /* external variables referenced. */
56 extern HWND SDL_HelperWindow;
60 static SDL_bool coinitialized = SDL_FALSE;
61 static LPDIRECTINPUT dinput = NULL;
62 extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
65 static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS]; /* array to hold joystick ID values */
66 static char *SYS_JoystickNames[MAX_JOYSTICKS];
67 static int SYS_NumJoysticks;
70 /* local prototypes */
71 static void SetDIerror(const char *function, HRESULT code);
72 static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE *
73 pdidInstance, VOID * pContext);
74 static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev,
76 static void SortDevObjects(SDL_Joystick *joystick);
77 static Uint8 TranslatePOV(DWORD value);
78 static int SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis,
80 static int SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat,
82 static int SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick,
83 Uint8 button, Uint8 state);
85 /* Taken from Wine - Thanks! */
86 DIOBJECTDATAFORMAT dfDIJoystick2[] = {
87 { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
88 { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
89 { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
90 { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
91 { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
92 { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
93 { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
94 { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
95 { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
96 { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
97 { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
98 { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
99 { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
100 { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
101 { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
102 { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
103 { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
104 { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
105 { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
106 { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
107 { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
108 { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
109 { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
110 { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
111 { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
112 { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
113 { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
114 { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
115 { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
116 { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
117 { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
118 { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
119 { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
120 { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
121 { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
122 { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
123 { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
124 { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
125 { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
126 { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
127 { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
128 { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
129 { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
130 { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
131 { NULL,DIJOFS_BUTTON(32),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
132 { NULL,DIJOFS_BUTTON(33),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
133 { NULL,DIJOFS_BUTTON(34),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
134 { NULL,DIJOFS_BUTTON(35),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
135 { NULL,DIJOFS_BUTTON(36),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
136 { NULL,DIJOFS_BUTTON(37),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
137 { NULL,DIJOFS_BUTTON(38),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
138 { NULL,DIJOFS_BUTTON(39),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
139 { NULL,DIJOFS_BUTTON(40),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
140 { NULL,DIJOFS_BUTTON(41),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
141 { NULL,DIJOFS_BUTTON(42),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
142 { NULL,DIJOFS_BUTTON(43),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
143 { NULL,DIJOFS_BUTTON(44),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
144 { NULL,DIJOFS_BUTTON(45),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
145 { NULL,DIJOFS_BUTTON(46),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
146 { NULL,DIJOFS_BUTTON(47),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
147 { NULL,DIJOFS_BUTTON(48),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
148 { NULL,DIJOFS_BUTTON(49),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
149 { NULL,DIJOFS_BUTTON(50),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
150 { NULL,DIJOFS_BUTTON(51),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
151 { NULL,DIJOFS_BUTTON(52),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
152 { NULL,DIJOFS_BUTTON(53),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
153 { NULL,DIJOFS_BUTTON(54),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
154 { NULL,DIJOFS_BUTTON(55),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
155 { NULL,DIJOFS_BUTTON(56),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
156 { NULL,DIJOFS_BUTTON(57),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
157 { NULL,DIJOFS_BUTTON(58),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
158 { NULL,DIJOFS_BUTTON(59),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
159 { NULL,DIJOFS_BUTTON(60),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
160 { NULL,DIJOFS_BUTTON(61),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
161 { NULL,DIJOFS_BUTTON(62),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
162 { NULL,DIJOFS_BUTTON(63),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
163 { NULL,DIJOFS_BUTTON(64),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
164 { NULL,DIJOFS_BUTTON(65),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
165 { NULL,DIJOFS_BUTTON(66),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
166 { NULL,DIJOFS_BUTTON(67),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
167 { NULL,DIJOFS_BUTTON(68),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
168 { NULL,DIJOFS_BUTTON(69),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
169 { NULL,DIJOFS_BUTTON(70),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
170 { NULL,DIJOFS_BUTTON(71),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
171 { NULL,DIJOFS_BUTTON(72),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
172 { NULL,DIJOFS_BUTTON(73),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
173 { NULL,DIJOFS_BUTTON(74),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
174 { NULL,DIJOFS_BUTTON(75),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
175 { NULL,DIJOFS_BUTTON(76),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
176 { NULL,DIJOFS_BUTTON(77),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
177 { NULL,DIJOFS_BUTTON(78),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
178 { NULL,DIJOFS_BUTTON(79),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
179 { NULL,DIJOFS_BUTTON(80),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
180 { NULL,DIJOFS_BUTTON(81),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
181 { NULL,DIJOFS_BUTTON(82),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
182 { NULL,DIJOFS_BUTTON(83),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
183 { NULL,DIJOFS_BUTTON(84),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
184 { NULL,DIJOFS_BUTTON(85),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
185 { NULL,DIJOFS_BUTTON(86),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
186 { NULL,DIJOFS_BUTTON(87),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
187 { NULL,DIJOFS_BUTTON(88),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
188 { NULL,DIJOFS_BUTTON(89),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
189 { NULL,DIJOFS_BUTTON(90),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
190 { NULL,DIJOFS_BUTTON(91),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
191 { NULL,DIJOFS_BUTTON(92),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
192 { NULL,DIJOFS_BUTTON(93),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
193 { NULL,DIJOFS_BUTTON(94),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
194 { NULL,DIJOFS_BUTTON(95),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
195 { NULL,DIJOFS_BUTTON(96),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
196 { NULL,DIJOFS_BUTTON(97),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
197 { NULL,DIJOFS_BUTTON(98),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
198 { NULL,DIJOFS_BUTTON(99),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
199 { NULL,DIJOFS_BUTTON(100),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
200 { NULL,DIJOFS_BUTTON(101),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
201 { NULL,DIJOFS_BUTTON(102),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
202 { NULL,DIJOFS_BUTTON(103),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
203 { NULL,DIJOFS_BUTTON(104),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
204 { NULL,DIJOFS_BUTTON(105),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
205 { NULL,DIJOFS_BUTTON(106),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
206 { NULL,DIJOFS_BUTTON(107),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
207 { NULL,DIJOFS_BUTTON(108),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
208 { NULL,DIJOFS_BUTTON(109),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
209 { NULL,DIJOFS_BUTTON(110),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
210 { NULL,DIJOFS_BUTTON(111),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
211 { NULL,DIJOFS_BUTTON(112),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
212 { NULL,DIJOFS_BUTTON(113),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
213 { NULL,DIJOFS_BUTTON(114),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
214 { NULL,DIJOFS_BUTTON(115),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
215 { NULL,DIJOFS_BUTTON(116),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
216 { NULL,DIJOFS_BUTTON(117),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
217 { NULL,DIJOFS_BUTTON(118),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
218 { NULL,DIJOFS_BUTTON(119),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
219 { NULL,DIJOFS_BUTTON(120),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
220 { NULL,DIJOFS_BUTTON(121),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
221 { NULL,DIJOFS_BUTTON(122),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
222 { NULL,DIJOFS_BUTTON(123),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
223 { NULL,DIJOFS_BUTTON(124),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
224 { NULL,DIJOFS_BUTTON(125),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
225 { NULL,DIJOFS_BUTTON(126),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
226 { NULL,DIJOFS_BUTTON(127),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
227 { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lVX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
228 { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lVY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
229 { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lVZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
230 { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lVRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
231 { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lVRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
232 { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lVRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
233 { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
234 { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
235 { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lAX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
236 { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lAY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
237 { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lAZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
238 { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lARx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
239 { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lARy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
240 { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lARz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
241 { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
242 { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
243 { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lFX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
244 { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lFY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
245 { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lFZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
246 { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lFRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
247 { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lFRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
248 { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lFRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
249 { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
250 { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
253 const DIDATAFORMAT c_dfDIJoystick2 = {
254 sizeof(DIDATAFORMAT),
255 sizeof(DIOBJECTDATAFORMAT),
258 SDL_arraysize(dfDIJoystick2),
263 /* Convert a DirectInput return code to a text message */
265 SetDIerror(const char *function, HRESULT code)
268 SDL_SetError("%s() [%s]: %s", function,
269 DXGetErrorString9A(code), DXGetErrorDescription9A(code));
271 SDL_SetError("%s() DirectX error %d", function, code);
275 /* Function to scan the system for joysticks.
276 * This function should set SDL_numjoysticks to the number of available
277 * joysticks. Joystick 0 should be the system default joystick.
278 * It should return 0, or -1 on an unrecoverable fatal error.
281 SDL_SYS_JoystickInit(void)
286 SYS_NumJoysticks = 0;
288 result = WIN_CoInitialize();
289 if (FAILED(result)) {
290 SetDIerror("CoInitialize", result);
294 coinitialized = SDL_TRUE;
296 result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
297 &IID_IDirectInput, (LPVOID)&dinput);
299 if (FAILED(result)) {
300 SDL_SYS_JoystickQuit();
301 SetDIerror("CoCreateInstance", result);
305 /* Because we used CoCreateInstance, we need to Initialize it, first. */
306 instance = GetModuleHandle(NULL);
307 if (instance == NULL) {
308 SDL_SYS_JoystickQuit();
309 SDL_SetError("GetModuleHandle() failed with error code %d.",
313 result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
315 if (FAILED(result)) {
316 SDL_SYS_JoystickQuit();
317 SetDIerror("IDirectInput::Initialize", result);
321 /* Look for joysticks, wheels, head trackers, gamepads, etc.. */
322 result = IDirectInput_EnumDevices(dinput,
324 EnumJoysticksCallback,
325 NULL, DIEDFL_ATTACHEDONLY);
327 return SYS_NumJoysticks;
331 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
333 SDL_memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance,
334 sizeof(DIDEVICEINSTANCE));
335 SYS_JoystickNames[SYS_NumJoysticks] = WIN_StringToUTF8(pdidInstance->tszProductName);
338 if (SYS_NumJoysticks >= MAX_JOYSTICKS)
341 return DIENUM_CONTINUE;
344 /* Function to get the device-dependent name of a joystick */
346 SDL_SYS_JoystickName(int index)
348 return SYS_JoystickNames[index];
351 /* Function to open a joystick for use.
352 The joystick to open is specified by the index field of the joystick.
353 This should fill the nbuttons and naxes fields of the joystick structure.
354 It returns 0, or -1 if there is an error.
357 SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
360 LPDIRECTINPUTDEVICE device;
363 SDL_memset(&dipdw, 0, sizeof(DIPROPDWORD));
364 dipdw.diph.dwSize = sizeof(DIPROPDWORD);
365 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
368 /* allocate memory for system specific hardware data */
370 (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
371 if (joystick->hwdata == NULL) {
375 SDL_memset(joystick->hwdata, 0, sizeof(struct joystick_hwdata));
376 joystick->hwdata->buffered = 1;
377 joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
380 IDirectInput_CreateDevice(dinput,
381 &SYS_Joystick[joystick->index].
382 guidInstance, &device, NULL);
383 if (FAILED(result)) {
384 SetDIerror("IDirectInput::CreateDevice", result);
388 /* Now get the IDirectInputDevice2 interface, instead. */
389 result = IDirectInputDevice_QueryInterface(device,
390 &IID_IDirectInputDevice2,
391 (LPVOID *) & joystick->
392 hwdata->InputDevice);
393 /* We are done with this object. Use the stored one from now on. */
394 IDirectInputDevice_Release(device);
396 if (FAILED(result)) {
397 SetDIerror("IDirectInputDevice::QueryInterface", result);
401 /* Aquire shared access. Exclusive access is required for forces,
404 IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->
405 InputDevice, SDL_HelperWindow,
408 if (FAILED(result)) {
409 SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result);
413 /* Use the extended data structure: DIJOYSTATE2. */
415 IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice,
417 if (FAILED(result)) {
418 SetDIerror("IDirectInputDevice2::SetDataFormat", result);
422 /* Get device capabilities */
424 IDirectInputDevice2_GetCapabilities(joystick->hwdata->InputDevice,
425 &joystick->hwdata->Capabilities);
427 if (FAILED(result)) {
428 SetDIerror("IDirectInputDevice2::GetCapabilities", result);
433 if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
435 result = IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
437 if (FAILED(result)) {
438 SetDIerror("IDirectInputDevice2::Acquire", result);
442 /* reset all accuators. */
444 IDirectInputDevice2_SendForceFeedbackCommand(joystick->hwdata->
448 /* Not necessarily supported, ignore if not supported.
449 if (FAILED(result)) {
450 SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand",
456 result = IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
458 if (FAILED(result)) {
459 SetDIerror("IDirectInputDevice2::Unacquire", result);
463 /* Turn on auto-centering for a ForceFeedback device (until told
465 dipdw.diph.dwObj = 0;
466 dipdw.diph.dwHow = DIPH_DEVICE;
467 dipdw.dwData = DIPROPAUTOCENTER_ON;
470 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
471 DIPROP_AUTOCENTER, &dipdw.diph);
473 /* Not necessarily supported, ignore if not supported.
474 if (FAILED(result)) {
475 SetDIerror("IDirectInputDevice2::SetProperty", result);
481 /* What buttons and axes does it have? */
482 IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice,
483 EnumDevObjectsCallback, joystick,
484 DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
486 /* Reorder the input objects. Some devices do not report the X axis as
487 * the first axis, for example. */
488 SortDevObjects(joystick);
490 dipdw.diph.dwObj = 0;
491 dipdw.diph.dwHow = DIPH_DEVICE;
492 dipdw.dwData = INPUT_QSIZE;
494 /* Set the buffer size */
496 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
497 DIPROP_BUFFERSIZE, &dipdw.diph);
499 if (result == DI_POLLEDDEVICE) {
500 /* This device doesn't support buffering, so we're forced
501 * to use less reliable polling. */
502 joystick->hwdata->buffered = 0;
503 } else if (FAILED(result)) {
504 SetDIerror("IDirectInputDevice2::SetProperty", result);
511 /* Sort using the data offset into the DInput struct.
512 * This gives a reasonable ordering for the inputs. */
514 SortDevFunc(const void *a, const void *b)
516 const input_t *inputA = (const input_t*)a;
517 const input_t *inputB = (const input_t*)b;
519 if (inputA->ofs < inputB->ofs)
521 if (inputA->ofs > inputB->ofs)
526 /* Sort the input objects and recalculate the indices for each input. */
528 SortDevObjects(SDL_Joystick *joystick)
530 input_t *inputs = joystick->hwdata->Inputs;
536 SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
538 for (n = 0; n < joystick->hwdata->NumInputs; n++)
540 switch (inputs[n].type)
543 inputs[n].num = nButtons;
548 inputs[n].num = nHats;
553 inputs[n].num = nAxis;
561 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
563 SDL_Joystick *joystick = (SDL_Joystick *) pvRef;
565 input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
567 in->ofs = dev->dwOfs;
569 if (dev->dwType & DIDFT_BUTTON) {
571 in->num = joystick->nbuttons;
572 joystick->nbuttons++;
573 } else if (dev->dwType & DIDFT_POV) {
575 in->num = joystick->nhats;
577 } else if (dev->dwType & DIDFT_AXIS) {
582 in->num = joystick->naxes;
584 diprg.diph.dwSize = sizeof(diprg);
585 diprg.diph.dwHeaderSize = sizeof(diprg.diph);
586 diprg.diph.dwObj = dev->dwOfs;
587 diprg.diph.dwHow = DIPH_BYOFFSET;
588 diprg.lMin = AXIS_MIN;
589 diprg.lMax = AXIS_MAX;
592 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
593 DIPROP_RANGE, &diprg.diph);
594 if (FAILED(result)) {
595 return DIENUM_CONTINUE; /* don't use this axis */
598 /* Set dead zone to 0. */
599 dilong.diph.dwSize = sizeof(dilong);
600 dilong.diph.dwHeaderSize = sizeof(dilong.diph);
601 dilong.diph.dwObj = dev->dwOfs;
602 dilong.diph.dwHow = DIPH_BYOFFSET;
605 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
606 DIPROP_DEADZONE, &dilong.diph);
607 if (FAILED(result)) {
608 return DIENUM_CONTINUE; /* don't use this axis */
613 /* not supported at this time */
614 return DIENUM_CONTINUE;
617 joystick->hwdata->NumInputs++;
619 if (joystick->hwdata->NumInputs == MAX_INPUTS) {
620 return DIENUM_STOP; /* too many */
623 return DIENUM_CONTINUE;
626 /* Function to update the state of a joystick - called as a device poll.
627 * This function shouldn't update the joystick structure directly,
628 * but instead should call SDL_PrivateJoystick*() to deliver events
629 * and update joystick device state.
632 SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick)
639 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
640 sizeof(DIJOYSTATE2), &state);
641 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
642 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
644 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
645 sizeof(DIJOYSTATE2), &state);
648 /* Set each known axis, button and POV. */
649 for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
650 const input_t *in = &joystick->hwdata->Inputs[i];
656 SDL_PrivateJoystickAxis_Int(joystick, in->num,
660 SDL_PrivateJoystickAxis_Int(joystick, in->num,
664 SDL_PrivateJoystickAxis_Int(joystick, in->num,
668 SDL_PrivateJoystickAxis_Int(joystick, in->num,
672 SDL_PrivateJoystickAxis_Int(joystick, in->num,
676 SDL_PrivateJoystickAxis_Int(joystick, in->num,
679 case DIJOFS_SLIDER(0):
680 SDL_PrivateJoystickAxis_Int(joystick, in->num,
681 (Sint16) state.rglSlider[0]);
683 case DIJOFS_SLIDER(1):
684 SDL_PrivateJoystickAxis_Int(joystick, in->num,
685 (Sint16) state.rglSlider[1]);
692 SDL_PrivateJoystickButton_Int(joystick, in->num,
701 Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs -
703 SDL_PrivateJoystickHat_Int(joystick, in->num, pos);
711 SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
716 DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
718 numevents = INPUT_QSIZE;
720 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
721 sizeof(DIDEVICEOBJECTDATA), evtbuf,
723 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
724 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
726 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
727 sizeof(DIDEVICEOBJECTDATA),
728 evtbuf, &numevents, 0);
731 /* Handle the events or punt */
735 for (i = 0; i < (int) numevents; ++i) {
738 for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
739 const input_t *in = &joystick->hwdata->Inputs[j];
741 if (evtbuf[i].dwOfs != in->ofs)
746 SDL_PrivateJoystickAxis(joystick, in->num,
747 (Sint16) evtbuf[i].dwData);
750 SDL_PrivateJoystickButton(joystick, in->num,
752 dwData ? SDL_PRESSED :
757 Uint8 pos = TranslatePOV(evtbuf[i].dwData);
758 SDL_PrivateJoystickHat(joystick, in->num, pos);
767 TranslatePOV(DWORD value)
769 const int HAT_VALS[] = {
771 SDL_HAT_UP | SDL_HAT_RIGHT,
773 SDL_HAT_DOWN | SDL_HAT_RIGHT,
775 SDL_HAT_DOWN | SDL_HAT_LEFT,
777 SDL_HAT_UP | SDL_HAT_LEFT
780 if (LOWORD(value) == 0xFFFF)
781 return SDL_HAT_CENTERED;
783 /* Round the value up: */
789 return SDL_HAT_CENTERED; /* shouldn't happen */
791 return HAT_VALS[value];
794 /* SDL_PrivateJoystick* doesn't discard duplicate events, so we need to
797 SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
799 if (joystick->axes[axis] != value)
800 return SDL_PrivateJoystickAxis(joystick, axis, value);
805 SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
807 if (joystick->hats[hat] != value)
808 return SDL_PrivateJoystickHat(joystick, hat, value);
813 SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick, Uint8 button,
816 if (joystick->buttons[button] != state)
817 return SDL_PrivateJoystickButton(joystick, button, state);
822 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
826 result = IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
827 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
828 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
829 IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
832 if (joystick->hwdata->buffered)
833 SDL_SYS_JoystickUpdate_Buffered(joystick);
835 SDL_SYS_JoystickUpdate_Polled(joystick);
838 /* Function to close a joystick after use */
840 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
842 IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
843 IDirectInputDevice2_Release(joystick->hwdata->InputDevice);
845 if (joystick->hwdata != NULL) {
846 /* free system specific hardware data */
847 SDL_free(joystick->hwdata);
851 /* Function to perform any system-specific joystick related cleanup */
853 SDL_SYS_JoystickQuit(void)
857 for (i = 0; i < SDL_arraysize(SYS_JoystickNames); ++i) {
858 if (SYS_JoystickNames[i]) {
859 SDL_free(SYS_JoystickNames[i]);
860 SYS_JoystickNames[i] = NULL;
864 if (dinput != NULL) {
865 IDirectInput_Release(dinput);
870 WIN_CoUninitialize();
871 coinitialized = SDL_FALSE;
875 #endif /* SDL_JOYSTICK_DINPUT */
877 /* vi: set ts=4 sw=4 expandtab: */