SDL  2.0
SDL_dinputjoystick.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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_internal.h"
22 
23 #include "../SDL_sysjoystick.h"
24 
25 #if SDL_JOYSTICK_DINPUT
26 
27 #include "SDL_windowsjoystick_c.h"
28 #include "SDL_dinputjoystick_c.h"
29 #include "SDL_xinputjoystick_c.h"
30 #include "../hidapi/SDL_hidapijoystick_c.h"
31 
32 #ifndef DIDFT_OPTIONAL
33 #define DIDFT_OPTIONAL 0x80000000
34 #endif
35 
36 #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
37 #define JOY_AXIS_THRESHOLD (((SDL_JOYSTICK_AXIS_MAX)-(SDL_JOYSTICK_AXIS_MIN))/100) /* 1% motion */
38 
39 #define CONVERT_MAGNITUDE(x) (((x)*10000) / 0x7FFF)
40 
41 /* external variables referenced. */
42 extern HWND SDL_HelperWindow;
43 
44 /* local variables */
45 static SDL_bool coinitialized = SDL_FALSE;
46 static LPDIRECTINPUT8 dinput = NULL;
47 static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
48 static UINT SDL_RawDevListCount = 0;
49 
50 /* Taken from Wine - Thanks! */
51 static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
52  { &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
53  { &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
54  { &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
55  { &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
56  { &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
57  { &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
58  { &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
59  { &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
60  { &GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
61  { &GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
62  { &GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
63  { &GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
64  { NULL, DIJOFS_BUTTON(0), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
65  { NULL, DIJOFS_BUTTON(1), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
66  { NULL, DIJOFS_BUTTON(2), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
67  { NULL, DIJOFS_BUTTON(3), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
68  { NULL, DIJOFS_BUTTON(4), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
69  { NULL, DIJOFS_BUTTON(5), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
70  { NULL, DIJOFS_BUTTON(6), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
71  { NULL, DIJOFS_BUTTON(7), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
72  { NULL, DIJOFS_BUTTON(8), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
73  { NULL, DIJOFS_BUTTON(9), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
74  { NULL, DIJOFS_BUTTON(10), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
75  { NULL, DIJOFS_BUTTON(11), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
76  { NULL, DIJOFS_BUTTON(12), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
77  { NULL, DIJOFS_BUTTON(13), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
78  { NULL, DIJOFS_BUTTON(14), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
79  { NULL, DIJOFS_BUTTON(15), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
80  { NULL, DIJOFS_BUTTON(16), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
81  { NULL, DIJOFS_BUTTON(17), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
82  { NULL, DIJOFS_BUTTON(18), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
83  { NULL, DIJOFS_BUTTON(19), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
84  { NULL, DIJOFS_BUTTON(20), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
85  { NULL, DIJOFS_BUTTON(21), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
86  { NULL, DIJOFS_BUTTON(22), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
87  { NULL, DIJOFS_BUTTON(23), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
88  { NULL, DIJOFS_BUTTON(24), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
89  { NULL, DIJOFS_BUTTON(25), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
90  { NULL, DIJOFS_BUTTON(26), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
91  { NULL, DIJOFS_BUTTON(27), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
92  { NULL, DIJOFS_BUTTON(28), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
93  { NULL, DIJOFS_BUTTON(29), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
94  { NULL, DIJOFS_BUTTON(30), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
95  { NULL, DIJOFS_BUTTON(31), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
96  { NULL, DIJOFS_BUTTON(32), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
97  { NULL, DIJOFS_BUTTON(33), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
98  { NULL, DIJOFS_BUTTON(34), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
99  { NULL, DIJOFS_BUTTON(35), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
100  { NULL, DIJOFS_BUTTON(36), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
101  { NULL, DIJOFS_BUTTON(37), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
102  { NULL, DIJOFS_BUTTON(38), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
103  { NULL, DIJOFS_BUTTON(39), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
104  { NULL, DIJOFS_BUTTON(40), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
105  { NULL, DIJOFS_BUTTON(41), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
106  { NULL, DIJOFS_BUTTON(42), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
107  { NULL, DIJOFS_BUTTON(43), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
108  { NULL, DIJOFS_BUTTON(44), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
109  { NULL, DIJOFS_BUTTON(45), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
110  { NULL, DIJOFS_BUTTON(46), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
111  { NULL, DIJOFS_BUTTON(47), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
112  { NULL, DIJOFS_BUTTON(48), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
113  { NULL, DIJOFS_BUTTON(49), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
114  { NULL, DIJOFS_BUTTON(50), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
115  { NULL, DIJOFS_BUTTON(51), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
116  { NULL, DIJOFS_BUTTON(52), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
117  { NULL, DIJOFS_BUTTON(53), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
118  { NULL, DIJOFS_BUTTON(54), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
119  { NULL, DIJOFS_BUTTON(55), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
120  { NULL, DIJOFS_BUTTON(56), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
121  { NULL, DIJOFS_BUTTON(57), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
122  { NULL, DIJOFS_BUTTON(58), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
123  { NULL, DIJOFS_BUTTON(59), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
124  { NULL, DIJOFS_BUTTON(60), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
125  { NULL, DIJOFS_BUTTON(61), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
126  { NULL, DIJOFS_BUTTON(62), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
127  { NULL, DIJOFS_BUTTON(63), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
128  { NULL, DIJOFS_BUTTON(64), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
129  { NULL, DIJOFS_BUTTON(65), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
130  { NULL, DIJOFS_BUTTON(66), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
131  { NULL, DIJOFS_BUTTON(67), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
132  { NULL, DIJOFS_BUTTON(68), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
133  { NULL, DIJOFS_BUTTON(69), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
134  { NULL, DIJOFS_BUTTON(70), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
135  { NULL, DIJOFS_BUTTON(71), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
136  { NULL, DIJOFS_BUTTON(72), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
137  { NULL, DIJOFS_BUTTON(73), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
138  { NULL, DIJOFS_BUTTON(74), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
139  { NULL, DIJOFS_BUTTON(75), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
140  { NULL, DIJOFS_BUTTON(76), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
141  { NULL, DIJOFS_BUTTON(77), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
142  { NULL, DIJOFS_BUTTON(78), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
143  { NULL, DIJOFS_BUTTON(79), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
144  { NULL, DIJOFS_BUTTON(80), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
145  { NULL, DIJOFS_BUTTON(81), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
146  { NULL, DIJOFS_BUTTON(82), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
147  { NULL, DIJOFS_BUTTON(83), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
148  { NULL, DIJOFS_BUTTON(84), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
149  { NULL, DIJOFS_BUTTON(85), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
150  { NULL, DIJOFS_BUTTON(86), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
151  { NULL, DIJOFS_BUTTON(87), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
152  { NULL, DIJOFS_BUTTON(88), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
153  { NULL, DIJOFS_BUTTON(89), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
154  { NULL, DIJOFS_BUTTON(90), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
155  { NULL, DIJOFS_BUTTON(91), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
156  { NULL, DIJOFS_BUTTON(92), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
157  { NULL, DIJOFS_BUTTON(93), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
158  { NULL, DIJOFS_BUTTON(94), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
159  { NULL, DIJOFS_BUTTON(95), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
160  { NULL, DIJOFS_BUTTON(96), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
161  { NULL, DIJOFS_BUTTON(97), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
162  { NULL, DIJOFS_BUTTON(98), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
163  { NULL, DIJOFS_BUTTON(99), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
164  { NULL, DIJOFS_BUTTON(100), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
165  { NULL, DIJOFS_BUTTON(101), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
166  { NULL, DIJOFS_BUTTON(102), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
167  { NULL, DIJOFS_BUTTON(103), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
168  { NULL, DIJOFS_BUTTON(104), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
169  { NULL, DIJOFS_BUTTON(105), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
170  { NULL, DIJOFS_BUTTON(106), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
171  { NULL, DIJOFS_BUTTON(107), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
172  { NULL, DIJOFS_BUTTON(108), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
173  { NULL, DIJOFS_BUTTON(109), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
174  { NULL, DIJOFS_BUTTON(110), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
175  { NULL, DIJOFS_BUTTON(111), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
176  { NULL, DIJOFS_BUTTON(112), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
177  { NULL, DIJOFS_BUTTON(113), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
178  { NULL, DIJOFS_BUTTON(114), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
179  { NULL, DIJOFS_BUTTON(115), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
180  { NULL, DIJOFS_BUTTON(116), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
181  { NULL, DIJOFS_BUTTON(117), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
182  { NULL, DIJOFS_BUTTON(118), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
183  { NULL, DIJOFS_BUTTON(119), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
184  { NULL, DIJOFS_BUTTON(120), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
185  { NULL, DIJOFS_BUTTON(121), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
186  { NULL, DIJOFS_BUTTON(122), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
187  { NULL, DIJOFS_BUTTON(123), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
188  { NULL, DIJOFS_BUTTON(124), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
189  { NULL, DIJOFS_BUTTON(125), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
190  { NULL, DIJOFS_BUTTON(126), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
191  { NULL, DIJOFS_BUTTON(127), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
192  { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
193  { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
194  { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
195  { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
196  { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
197  { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
198  { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
199  { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
200  { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
201  { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
202  { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
203  { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
204  { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
205  { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
206  { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
207  { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
208  { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
209  { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
210  { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
211  { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
212  { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
213  { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
214  { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
215  { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
216 };
217 
218 const DIDATAFORMAT SDL_c_dfDIJoystick2 = {
219  sizeof(DIDATAFORMAT),
220  sizeof(DIOBJECTDATAFORMAT),
221  DIDF_ABSAXIS,
222  sizeof(DIJOYSTATE2),
223  SDL_arraysize(dfDIJoystick2),
224  dfDIJoystick2
225 };
226 
227 /* Convert a DirectInput return code to a text message */
228 static int
229 SetDIerror(const char *function, HRESULT code)
230 {
231  /*
232  return SDL_SetError("%s() [%s]: %s", function,
233  DXGetErrorString9A(code), DXGetErrorDescription9A(code));
234  */
235  return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code);
236 }
237 
238 #if 0 /* Microsoft recommended implementation, but slower than checking raw devices */
239 #define COBJMACROS
240 #include <wbemidl.h>
241 #include <oleauto.h>
242 
243 static const IID CLSID_WbemLocator = { 0x4590f811, 0x1d3a, 0x11d0,{ 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } };
244 static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf,{ 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } };
245 
246 static SDL_bool
247 WIN_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
248 {
249  IWbemLocator* pIWbemLocator = NULL;
250  IEnumWbemClassObject* pEnumDevices = NULL;
251  IWbemClassObject* pDevices[20];
252  IWbemServices* pIWbemServices = NULL;
253  BSTR bstrNamespace = NULL;
254  BSTR bstrDeviceID = NULL;
255  BSTR bstrClassName = NULL;
256  DWORD uReturned = 0;
257  SDL_bool bIsXinputDevice = SDL_FALSE;
258  UINT iDevice = 0;
259  VARIANT var;
260  HRESULT hr;
261 
262  SDL_zeroa(pDevices);
263 
264  // Create WMI
265  hr = CoCreateInstance(&CLSID_WbemLocator,
266  NULL,
267  CLSCTX_INPROC_SERVER,
268  &IID_IWbemLocator,
269  (LPVOID*)&pIWbemLocator);
270  if (FAILED(hr) || pIWbemLocator == NULL)
271  goto LCleanup;
272 
273  bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == NULL) goto LCleanup;
274  bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == NULL) goto LCleanup;
275  bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == NULL) goto LCleanup;
276 
277  // Connect to WMI
278  hr = IWbemLocator_ConnectServer(pIWbemLocator, bstrNamespace, NULL, NULL, 0L,
279  0L, NULL, NULL, &pIWbemServices);
280  if (FAILED(hr) || pIWbemServices == NULL) {
281  goto LCleanup;
282  }
283 
284  // Switch security level to IMPERSONATE.
285  CoSetProxyBlanket((IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
286  RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
287 
288  hr = IWbemServices_CreateInstanceEnum(pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices);
289  if (FAILED(hr) || pEnumDevices == NULL)
290  goto LCleanup;
291 
292  // Loop over all devices
293  for (;;) {
294  // Get 20 at a time
295  hr = IEnumWbemClassObject_Next(pEnumDevices, 10000, SDL_arraysize(pDevices), pDevices, &uReturned);
296  if (FAILED(hr)) {
297  goto LCleanup;
298  }
299  if (uReturned == 0) {
300  break;
301  }
302 
303  for (iDevice = 0; iDevice < uReturned; iDevice++) {
304  // For each device, get its device ID
305  hr = IWbemClassObject_Get(pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL);
306  if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) {
307  // Check if the device ID contains "IG_". If it does, then it's an XInput device
308  // This information can not be found from DirectInput
309  if (SDL_wcsstr(var.bstrVal, L"IG_")) {
310  char *bstrVal = WIN_StringToUTF8(var.bstrVal);
311 
312  // If it does, then get the VID/PID from var.bstrVal
313  DWORD dwPid = 0, dwVid = 0, dwVidPid;
314  const char *strVid, *strPid;
315  strVid = SDL_strstr(bstrVal, "VID_");
316  if (strVid && SDL_sscanf(strVid, "VID_%4X", &dwVid) != 1)
317  dwVid = 0;
318  strPid = SDL_strstr(bstrVal, "PID_");
319  if (strPid && SDL_sscanf(strPid, "PID_%4X", &dwPid) != 1)
320  dwPid = 0;
321 
322  SDL_free(bstrVal);
323 
324  // Compare the VID/PID to the DInput device
325  dwVidPid = MAKELONG(dwVid, dwPid);
326  if (dwVidPid == pGuidProductFromDirectInput->Data1) {
327  bIsXinputDevice = SDL_TRUE;
328  goto LCleanup;
329  }
330  }
331  }
332  IWbemClassObject_Release(pDevices[iDevice]);
333  }
334  }
335 
336 LCleanup:
337  if (bstrNamespace) {
338  SysFreeString(bstrNamespace);
339  }
340  if (bstrDeviceID) {
341  SysFreeString(bstrDeviceID);
342  }
343  if (bstrClassName) {
344  SysFreeString(bstrClassName);
345  }
346  for (iDevice = 0; iDevice < SDL_arraysize(pDevices); iDevice++) {
347  if (pDevices[iDevice]) {
348  IWbemClassObject_Release(pDevices[iDevice]);
349  }
350  }
351  if (pEnumDevices) {
352  IEnumWbemClassObject_Release(pEnumDevices);
353  }
354  if (pIWbemLocator) {
355  IWbemLocator_Release(pIWbemLocator);
356  }
357  if (pIWbemServices) {
358  IWbemServices_Release(pIWbemServices);
359  }
360 
361  return bIsXinputDevice;
362 }
363 #endif /* 0 */
364 
365 static SDL_bool
366 SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
367 {
368  UINT i;
369 
370  if (!SDL_XINPUT_Enabled()) {
371  return SDL_FALSE;
372  }
373 
374  if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) {
375  Uint16 vendor_id = (Uint16)LOWORD(pGuidProductFromDirectInput->Data1);
376  Uint16 product_id = (Uint16)HIWORD(pGuidProductFromDirectInput->Data1);
377  SDL_GameControllerType type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0);
380  (vendor_id == 0x28DE && product_id == 0x11FF)) {
381  return SDL_TRUE;
382  }
383  }
384 
385  /* Go through RAWINPUT (WinXP and later) to find HID devices. */
386  /* Cache this if we end up using it. */
387  if (SDL_RawDevList == NULL) {
388  if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
389  return SDL_FALSE; /* oh well. */
390  }
391 
392  SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
393  if (SDL_RawDevList == NULL) {
394  SDL_OutOfMemory();
395  return SDL_FALSE;
396  }
397 
398  if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
399  SDL_free(SDL_RawDevList);
400  SDL_RawDevList = NULL;
401  return SDL_FALSE; /* oh well. */
402  }
403  }
404 
405  for (i = 0; i < SDL_RawDevListCount; i++) {
406  RID_DEVICE_INFO rdi;
407  char devName[128];
408  UINT rdiSize = sizeof(rdi);
409  UINT nameSize = SDL_arraysize(devName);
410 
411  rdi.cbSize = sizeof(rdi);
412  if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
413  (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
414  (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
415  (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
416  (SDL_strstr(devName, "IG_") != NULL)) {
417  return SDL_TRUE;
418  }
419  }
420 
421  return SDL_FALSE;
422 }
423 
424 void FreeRumbleEffectData(DIEFFECT *effect)
425 {
426  if (!effect) {
427  return;
428  }
429  SDL_free(effect->rgdwAxes);
430  SDL_free(effect->rglDirection);
431  SDL_free(effect->lpvTypeSpecificParams);
432  SDL_free(effect);
433 }
434 
435 DIEFFECT *CreateRumbleEffectData(Sint16 magnitude)
436 {
437  DIEFFECT *effect;
438  DIPERIODIC *periodic;
439 
440  /* Create the effect */
441  effect = (DIEFFECT *)SDL_calloc(1, sizeof(*effect));
442  if (!effect) {
443  return NULL;
444  }
445  effect->dwSize = sizeof(*effect);
446  effect->dwGain = 10000;
447  effect->dwFlags = DIEFF_OBJECTOFFSETS;
448  effect->dwDuration = SDL_MAX_RUMBLE_DURATION_MS * 1000; /* In microseconds. */
449  effect->dwTriggerButton = DIEB_NOTRIGGER;
450 
451  effect->cAxes = 2;
452  effect->rgdwAxes = (DWORD *)SDL_calloc(effect->cAxes, sizeof(DWORD));
453  if (!effect->rgdwAxes) {
454  FreeRumbleEffectData(effect);
455  return NULL;
456  }
457 
458  effect->rglDirection = (LONG *)SDL_calloc(effect->cAxes, sizeof(LONG));
459  if (!effect->rglDirection) {
460  FreeRumbleEffectData(effect);
461  return NULL;
462  }
463  effect->dwFlags |= DIEFF_CARTESIAN;
464 
465  periodic = (DIPERIODIC *)SDL_calloc(1, sizeof(*periodic));
466  if (!periodic) {
467  FreeRumbleEffectData(effect);
468  return NULL;
469  }
470  periodic->dwMagnitude = CONVERT_MAGNITUDE(magnitude);
471  periodic->dwPeriod = 1000000;
472 
473  effect->cbTypeSpecificParams = sizeof(*periodic);
474  effect->lpvTypeSpecificParams = periodic;
475 
476  return effect;
477 }
478 
479 int
481 {
482  HRESULT result;
483  HINSTANCE instance;
484 
486  if (FAILED(result)) {
487  return SetDIerror("CoInitialize", result);
488  }
489 
490  coinitialized = SDL_TRUE;
491 
492  result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
493  &IID_IDirectInput8, (LPVOID)&dinput);
494 
495  if (FAILED(result)) {
496  return SetDIerror("CoCreateInstance", result);
497  }
498 
499  /* Because we used CoCreateInstance, we need to Initialize it, first. */
500  instance = GetModuleHandle(NULL);
501  if (instance == NULL) {
502  return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
503  }
504  result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
505 
506  if (FAILED(result)) {
507  return SetDIerror("IDirectInput::Initialize", result);
508  }
509  return 0;
510 }
511 
512 /* helper function for direct input, gets called for each connected joystick */
513 static BOOL CALLBACK
514 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
515 {
516  JoyStick_DeviceData *pNewJoystick;
517  JoyStick_DeviceData *pPrevJoystick = NULL;
518  const DWORD devtype = (pdidInstance->dwDevType & 0xFF);
519  Uint16 *guid16;
520  Uint16 vendor = 0;
521  Uint16 product = 0;
522  Uint16 version = 0;
523  WCHAR hidPath[MAX_PATH];
524  const char *name;
525 
526  if (devtype == DI8DEVTYPE_SUPPLEMENTAL) {
527  /* Add any supplemental devices that should be ignored here */
528 #define MAKE_TABLE_ENTRY(VID, PID) ((((DWORD)PID)<<16)|VID)
529  static DWORD ignored_devices[] = {
530  MAKE_TABLE_ENTRY(0, 0)
531  };
532 #undef MAKE_TABLE_ENTRY
533  unsigned int i;
534 
535  for (i = 0; i < SDL_arraysize(ignored_devices); ++i) {
536  if (pdidInstance->guidProduct.Data1 == ignored_devices[i]) {
537  return DIENUM_CONTINUE;
538  }
539  }
540  }
541 
542  if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
543  return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
544  }
545 
546  {
547  HRESULT result;
548  LPDIRECTINPUTDEVICE8 device;
549  LPDIRECTINPUTDEVICE8 InputDevice;
550  DIPROPGUIDANDPATH dipdw2;
551 
552  result = IDirectInput8_CreateDevice(dinput, &(pdidInstance->guidInstance), &device, NULL);
553  if (FAILED(result)) {
554  return DIENUM_CONTINUE; /* better luck next time? */
555  }
556 
557  /* Now get the IDirectInputDevice8 interface, instead. */
558  result = IDirectInputDevice8_QueryInterface(device, &IID_IDirectInputDevice8, (LPVOID *)&InputDevice);
559  /* We are done with this object. Use the stored one from now on. */
560  IDirectInputDevice8_Release(device);
561  if (FAILED(result)) {
562  return DIENUM_CONTINUE; /* better luck next time? */
563  }
564  dipdw2.diph.dwSize = sizeof(dipdw2);
565  dipdw2.diph.dwHeaderSize = sizeof(dipdw2.diph);
566  dipdw2.diph.dwObj = 0; // device property
567  dipdw2.diph.dwHow = DIPH_DEVICE;
568 
569  result = IDirectInputDevice8_GetProperty(InputDevice, DIPROP_GUIDANDPATH, &dipdw2.diph);
570  IDirectInputDevice8_Release(InputDevice);
571  if (FAILED(result)) {
572  return DIENUM_CONTINUE; /* better luck next time? */
573  }
574 
575  /* Get device path, compare that instead of GUID, additionally update GUIDs of joysticks with matching paths, in case they're not open yet. */
576  SDL_wcslcpy(hidPath, dipdw2.wszPath, SDL_arraysize(hidPath));
577  }
578 
579  pNewJoystick = *(JoyStick_DeviceData **)pContext;
580  while (pNewJoystick) {
581  if (SDL_wcscmp(pNewJoystick->hidPath, hidPath) == 0) {
582  /* if we are replacing the front of the list then update it */
583  if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
584  *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
585  } else if (pPrevJoystick) {
586  pPrevJoystick->pNext = pNewJoystick->pNext;
587  }
588 
589  // Update with new guid/etc, if it has changed
590  pNewJoystick->dxdevice = *pdidInstance;
591 
592  pNewJoystick->pNext = SYS_Joystick;
593  SYS_Joystick = pNewJoystick;
594 
595  return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
596  }
597 
598  pPrevJoystick = pNewJoystick;
599  pNewJoystick = pNewJoystick->pNext;
600  }
601 
602  pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
603  if (!pNewJoystick) {
604  return DIENUM_CONTINUE; /* better luck next time? */
605  }
606 
607  SDL_zerop(pNewJoystick);
608  SDL_wcslcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath));
609  SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE));
610  SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
611 
612  guid16 = (Uint16 *)pNewJoystick->guid.data;
613  if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
614  vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
615  product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
616  version = 0;
617 
618  *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
619  *guid16++ = 0;
620  *guid16++ = SDL_SwapLE16(vendor);
621  *guid16++ = 0;
622  *guid16++ = SDL_SwapLE16(product);
623  *guid16++ = 0;
624  *guid16++ = SDL_SwapLE16(version);
625  *guid16++ = 0;
626  } else {
628  *guid16++ = 0;
629  SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
630  }
631 
632  name = SDL_GetCustomJoystickName(vendor, product);
633  if (name) {
634  pNewJoystick->joystickname = SDL_strdup(name);
635  } else {
636  pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
637  }
638  if (!pNewJoystick->joystickname) {
639  SDL_free(pNewJoystick);
640  return DIENUM_CONTINUE; /* better luck next time? */
641  }
642 
643  if (SDL_strstr(pNewJoystick->joystickname, " XINPUT ") != NULL) {
644  /* This is a duplicate interface for a controller that will show up with XInput,
645  e.g. Xbox One Elite Series 2 in Bluetooth mode.
646  */
647  SDL_free(pNewJoystick->joystickname);
648  SDL_free(pNewJoystick);
649  return DIENUM_CONTINUE;
650  }
651 
652  if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
653  SDL_free(pNewJoystick->joystickname);
654  SDL_free(pNewJoystick);
655  return DIENUM_CONTINUE;
656  }
657 
658 #ifdef SDL_JOYSTICK_HIDAPI
659  if (HIDAPI_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) {
660  /* The HIDAPI driver is taking care of this device */
661  SDL_free(pNewJoystick->joystickname);
662  SDL_free(pNewJoystick);
663  return DIENUM_CONTINUE;
664  }
665 #endif
666 
667  WINDOWS_AddJoystickDevice(pNewJoystick);
668 
669  return DIENUM_CONTINUE; /* get next device, please */
670 }
671 
672 void
674 {
675  IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
676 
677  if (SDL_RawDevList) {
678  SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */
679  SDL_RawDevList = NULL;
680  }
681  SDL_RawDevListCount = 0;
682 }
683 
684 static BOOL CALLBACK
685 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
686 {
687  SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
688  HRESULT result;
689  input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
690 
691  if (dev->dwType & DIDFT_BUTTON) {
692  in->type = BUTTON;
693  in->num = joystick->nbuttons;
694  in->ofs = DIJOFS_BUTTON(in->num);
695  joystick->nbuttons++;
696  } else if (dev->dwType & DIDFT_POV) {
697  in->type = HAT;
698  in->num = joystick->nhats;
699  in->ofs = DIJOFS_POV(in->num);
700  joystick->nhats++;
701  } else if (dev->dwType & DIDFT_AXIS) {
702  DIPROPRANGE diprg;
703  DIPROPDWORD dilong;
704 
705  in->type = AXIS;
706  in->num = joystick->naxes;
707  if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
708  in->ofs = DIJOFS_X;
709  else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
710  in->ofs = DIJOFS_Y;
711  else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
712  in->ofs = DIJOFS_Z;
713  else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
714  in->ofs = DIJOFS_RX;
715  else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
716  in->ofs = DIJOFS_RY;
717  else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
718  in->ofs = DIJOFS_RZ;
719  else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
720  in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
721  ++joystick->hwdata->NumSliders;
722  } else {
723  return DIENUM_CONTINUE; /* not an axis we can grok */
724  }
725 
726  diprg.diph.dwSize = sizeof(diprg);
727  diprg.diph.dwHeaderSize = sizeof(diprg.diph);
728  diprg.diph.dwObj = dev->dwType;
729  diprg.diph.dwHow = DIPH_BYID;
730  diprg.lMin = SDL_JOYSTICK_AXIS_MIN;
731  diprg.lMax = SDL_JOYSTICK_AXIS_MAX;
732 
733  result =
734  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
735  DIPROP_RANGE, &diprg.diph);
736  if (FAILED(result)) {
737  return DIENUM_CONTINUE; /* don't use this axis */
738  }
739 
740  /* Set dead zone to 0. */
741  dilong.diph.dwSize = sizeof(dilong);
742  dilong.diph.dwHeaderSize = sizeof(dilong.diph);
743  dilong.diph.dwObj = dev->dwType;
744  dilong.diph.dwHow = DIPH_BYID;
745  dilong.dwData = 0;
746  result =
747  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
748  DIPROP_DEADZONE, &dilong.diph);
749  if (FAILED(result)) {
750  return DIENUM_CONTINUE; /* don't use this axis */
751  }
752 
753  joystick->naxes++;
754  } else {
755  /* not supported at this time */
756  return DIENUM_CONTINUE;
757  }
758 
759  joystick->hwdata->NumInputs++;
760 
761  if (joystick->hwdata->NumInputs == MAX_INPUTS) {
762  return DIENUM_STOP; /* too many */
763  }
764 
765  return DIENUM_CONTINUE;
766 }
767 
768 /* Sort using the data offset into the DInput struct.
769  * This gives a reasonable ordering for the inputs.
770  */
771 static int
772 SortDevFunc(const void *a, const void *b)
773 {
774  const input_t *inputA = (const input_t*)a;
775  const input_t *inputB = (const input_t*)b;
776 
777  if (inputA->ofs < inputB->ofs)
778  return -1;
779  if (inputA->ofs > inputB->ofs)
780  return 1;
781  return 0;
782 }
783 
784 /* Sort the input objects and recalculate the indices for each input. */
785 static void
786 SortDevObjects(SDL_Joystick *joystick)
787 {
788  input_t *inputs = joystick->hwdata->Inputs;
789  int nButtons = 0;
790  int nHats = 0;
791  int nAxis = 0;
792  int n;
793 
794  SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
795 
796  for (n = 0; n < joystick->hwdata->NumInputs; n++) {
797  switch (inputs[n].type) {
798  case BUTTON:
799  inputs[n].num = nButtons;
800  nButtons++;
801  break;
802 
803  case HAT:
804  inputs[n].num = nHats;
805  nHats++;
806  break;
807 
808  case AXIS:
809  inputs[n].num = nAxis;
810  nAxis++;
811  break;
812  }
813  }
814 }
815 
816 int
817 SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
818 {
819  HRESULT result;
820  LPDIRECTINPUTDEVICE8 device;
821  DIPROPDWORD dipdw;
822 
823  joystick->hwdata->buffered = SDL_TRUE;
824  joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
825 
826  SDL_zero(dipdw);
827  dipdw.diph.dwSize = sizeof(DIPROPDWORD);
828  dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
829 
830  result =
831  IDirectInput8_CreateDevice(dinput,
832  &(joystickdevice->dxdevice.guidInstance), &device, NULL);
833  if (FAILED(result)) {
834  return SetDIerror("IDirectInput::CreateDevice", result);
835  }
836 
837  /* Now get the IDirectInputDevice8 interface, instead. */
838  result = IDirectInputDevice8_QueryInterface(device,
839  &IID_IDirectInputDevice8,
840  (LPVOID *)& joystick->
841  hwdata->InputDevice);
842  /* We are done with this object. Use the stored one from now on. */
843  IDirectInputDevice8_Release(device);
844 
845  if (FAILED(result)) {
846  return SetDIerror("IDirectInputDevice8::QueryInterface", result);
847  }
848 
849  /* Acquire shared access. Exclusive access is required for forces,
850  * though. */
851  result =
852  IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
853  InputDevice, SDL_HelperWindow,
854  DISCL_EXCLUSIVE |
855  DISCL_BACKGROUND);
856  if (FAILED(result)) {
857  return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
858  }
859 
860  /* Use the extended data structure: DIJOYSTATE2. */
861  result =
862  IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
863  &SDL_c_dfDIJoystick2);
864  if (FAILED(result)) {
865  return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
866  }
867 
868  /* Get device capabilities */
869  result =
870  IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
871  &joystick->hwdata->Capabilities);
872  if (FAILED(result)) {
873  return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
874  }
875 
876  /* Force capable? */
877  if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
878  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
879  if (FAILED(result)) {
880  return SetDIerror("IDirectInputDevice8::Acquire", result);
881  }
882 
883  /* reset all actuators. */
884  result =
885  IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
886  InputDevice,
887  DISFFC_RESET);
888 
889  /* Not necessarily supported, ignore if not supported.
890  if (FAILED(result)) {
891  return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
892  }
893  */
894 
895  result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
896 
897  if (FAILED(result)) {
898  return SetDIerror("IDirectInputDevice8::Unacquire", result);
899  }
900 
901  /* Turn on auto-centering for a ForceFeedback device (until told
902  * otherwise). */
903  dipdw.diph.dwObj = 0;
904  dipdw.diph.dwHow = DIPH_DEVICE;
905  dipdw.dwData = DIPROPAUTOCENTER_ON;
906 
907  result =
908  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
909  DIPROP_AUTOCENTER, &dipdw.diph);
910 
911  /* Not necessarily supported, ignore if not supported.
912  if (FAILED(result)) {
913  return SetDIerror("IDirectInputDevice8::SetProperty", result);
914  }
915  */
916  }
917 
918  /* What buttons and axes does it have? */
919  IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
920  EnumDevObjectsCallback, joystick,
921  DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
922 
923  /* Reorder the input objects. Some devices do not report the X axis as
924  * the first axis, for example. */
925  SortDevObjects(joystick);
926 
927  dipdw.diph.dwObj = 0;
928  dipdw.diph.dwHow = DIPH_DEVICE;
929  dipdw.dwData = INPUT_QSIZE;
930 
931  /* Set the buffer size */
932  result =
933  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
934  DIPROP_BUFFERSIZE, &dipdw.diph);
935 
936  if (result == DI_POLLEDDEVICE) {
937  /* This device doesn't support buffering, so we're forced
938  * to use less reliable polling. */
939  joystick->hwdata->buffered = SDL_FALSE;
940  } else if (FAILED(result)) {
941  return SetDIerror("IDirectInputDevice8::SetProperty", result);
942  }
943  return 0;
944 }
945 
946 static int
947 SDL_DINPUT_JoystickInitRumble(SDL_Joystick * joystick, Sint16 magnitude)
948 {
949  HRESULT result;
950 
951  /* Reset and then enable actuators */
952  result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_RESET);
953  if (result == DIERR_INPUTLOST || result == DIERR_NOTEXCLUSIVEACQUIRED) {
954  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
955  if (SUCCEEDED(result)) {
956  result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_RESET);
957  }
958  }
959  if (FAILED(result)) {
960  return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand(DISFFC_RESET)", result);
961  }
962 
963  result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_SETACTUATORSON);
964  if (FAILED(result)) {
965  return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand(DISFFC_SETACTUATORSON)", result);
966  }
967 
968  /* Create the effect */
969  joystick->hwdata->ffeffect = CreateRumbleEffectData(magnitude);
970  if (!joystick->hwdata->ffeffect) {
971  return SDL_OutOfMemory();
972  }
973 
974  result = IDirectInputDevice8_CreateEffect(joystick->hwdata->InputDevice, &GUID_Sine,
975  joystick->hwdata->ffeffect, &joystick->hwdata->ffeffect_ref, NULL);
976  if (FAILED(result)) {
977  return SetDIerror("IDirectInputDevice8::CreateEffect", result);
978  }
979  return 0;
980 }
981 
982 int
983 SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
984 {
985  HRESULT result;
986 
987  /* Scale and average the two rumble strengths */
988  Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
989 
990  if (!(joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK)) {
991  return SDL_Unsupported();
992  }
993 
994  if (joystick->hwdata->ff_initialized) {
995  DIPERIODIC *periodic = ((DIPERIODIC *)joystick->hwdata->ffeffect->lpvTypeSpecificParams);
996  periodic->dwMagnitude = CONVERT_MAGNITUDE(magnitude);
997 
998  result = IDirectInputEffect_SetParameters(joystick->hwdata->ffeffect_ref, joystick->hwdata->ffeffect, (DIEP_DURATION | DIEP_TYPESPECIFICPARAMS));
999  if (result == DIERR_INPUTLOST) {
1000  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1001  if (SUCCEEDED(result)) {
1002  result = IDirectInputEffect_SetParameters(joystick->hwdata->ffeffect_ref, joystick->hwdata->ffeffect, (DIEP_DURATION | DIEP_TYPESPECIFICPARAMS));
1003  }
1004  }
1005  if (FAILED(result)) {
1006  return SetDIerror("IDirectInputDevice8::SetParameters", result);
1007  }
1008  } else {
1009  if (SDL_DINPUT_JoystickInitRumble(joystick, magnitude) < 0) {
1010  return -1;
1011  }
1012  joystick->hwdata->ff_initialized = SDL_TRUE;
1013  }
1014 
1015  result = IDirectInputEffect_Start(joystick->hwdata->ffeffect_ref, 1, 0);
1016  if (result == DIERR_INPUTLOST || result == DIERR_NOTEXCLUSIVEACQUIRED) {
1017  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1018  if (SUCCEEDED(result)) {
1019  result = IDirectInputEffect_Start(joystick->hwdata->ffeffect_ref, 1, 0);
1020  }
1021  }
1022  if (FAILED(result)) {
1023  return SetDIerror("IDirectInputDevice8::Start", result);
1024  }
1025  return 0;
1026 }
1027 
1028 static Uint8
1029 TranslatePOV(DWORD value)
1030 {
1031  const int HAT_VALS[] = {
1032  SDL_HAT_UP,
1034  SDL_HAT_RIGHT,
1036  SDL_HAT_DOWN,
1038  SDL_HAT_LEFT,
1040  };
1041 
1042  if (LOWORD(value) == 0xFFFF)
1043  return SDL_HAT_CENTERED;
1044 
1045  /* Round the value up: */
1046  value += 4500 / 2;
1047  value %= 36000;
1048  value /= 4500;
1049 
1050  if (value >= 8)
1051  return SDL_HAT_CENTERED; /* shouldn't happen */
1052 
1053  return HAT_VALS[value];
1054 }
1055 
1056 static void
1057 UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
1058 {
1059  int i;
1060  HRESULT result;
1061  DWORD numevents;
1062  DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
1063 
1064  numevents = INPUT_QSIZE;
1065  result =
1066  IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
1067  sizeof(DIDEVICEOBJECTDATA), evtbuf,
1068  &numevents, 0);
1069  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1070  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1071  result =
1072  IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
1073  sizeof(DIDEVICEOBJECTDATA),
1074  evtbuf, &numevents, 0);
1075  }
1076 
1077  /* Handle the events or punt */
1078  if (FAILED(result)) {
1079  return;
1080  }
1081 
1082  for (i = 0; i < (int)numevents; ++i) {
1083  int j;
1084 
1085  for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
1086  const input_t *in = &joystick->hwdata->Inputs[j];
1087 
1088  if (evtbuf[i].dwOfs != in->ofs)
1089  continue;
1090 
1091  switch (in->type) {
1092  case AXIS:
1093  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
1094  break;
1095  case BUTTON:
1096  SDL_PrivateJoystickButton(joystick, in->num,
1097  (Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
1098  break;
1099  case HAT:
1100  {
1101  Uint8 pos = TranslatePOV(evtbuf[i].dwData);
1102  SDL_PrivateJoystickHat(joystick, in->num, pos);
1103  }
1104  break;
1105  }
1106  }
1107  }
1108 }
1109 
1110 /* Function to update the state of a joystick - called as a device poll.
1111  * This function shouldn't update the joystick structure directly,
1112  * but instead should call SDL_PrivateJoystick*() to deliver events
1113  * and update joystick device state.
1114  */
1115 static void
1116 UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
1117 {
1118  DIJOYSTATE2 state;
1119  HRESULT result;
1120  int i;
1121 
1122  result =
1123  IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
1124  sizeof(DIJOYSTATE2), &state);
1125  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1126  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1127  result =
1128  IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
1129  sizeof(DIJOYSTATE2), &state);
1130  }
1131 
1132  if (result != DI_OK) {
1133  return;
1134  }
1135 
1136  /* Set each known axis, button and POV. */
1137  for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
1138  const input_t *in = &joystick->hwdata->Inputs[i];
1139 
1140  switch (in->type) {
1141  case AXIS:
1142  switch (in->ofs) {
1143  case DIJOFS_X:
1144  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
1145  break;
1146  case DIJOFS_Y:
1147  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
1148  break;
1149  case DIJOFS_Z:
1150  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
1151  break;
1152  case DIJOFS_RX:
1153  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
1154  break;
1155  case DIJOFS_RY:
1156  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
1157  break;
1158  case DIJOFS_RZ:
1159  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
1160  break;
1161  case DIJOFS_SLIDER(0):
1162  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
1163  break;
1164  case DIJOFS_SLIDER(1):
1165  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
1166  break;
1167  }
1168  break;
1169 
1170  case BUTTON:
1171  SDL_PrivateJoystickButton(joystick, in->num,
1172  (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
1173  break;
1174  case HAT:
1175  {
1176  Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
1177  SDL_PrivateJoystickHat(joystick, in->num, pos);
1178  break;
1179  }
1180  }
1181  }
1182 }
1183 
1184 void
1185 SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
1186 {
1187  HRESULT result;
1188 
1189  result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
1190  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1191  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1192  IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
1193  }
1194 
1195  if (joystick->hwdata->buffered) {
1196  UpdateDINPUTJoystickState_Buffered(joystick);
1197  } else {
1198  UpdateDINPUTJoystickState_Polled(joystick);
1199  }
1200 }
1201 
1202 void
1203 SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
1204 {
1205  if (joystick->hwdata->ffeffect_ref) {
1206  IDirectInputEffect_Unload(joystick->hwdata->ffeffect_ref);
1207  joystick->hwdata->ffeffect_ref = NULL;
1208  }
1209  if (joystick->hwdata->ffeffect) {
1210  FreeRumbleEffectData(joystick->hwdata->ffeffect);
1211  joystick->hwdata->ffeffect = NULL;
1212  }
1213  IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
1214  IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
1215  joystick->hwdata->ff_initialized = SDL_FALSE;
1216 }
1217 
1218 void
1220 {
1221  if (dinput != NULL) {
1222  IDirectInput8_Release(dinput);
1223  dinput = NULL;
1224  }
1225 
1226  if (coinitialized) {
1228  coinitialized = SDL_FALSE;
1229  }
1230 }
1231 
1232 #else /* !SDL_JOYSTICK_DINPUT */
1233 
1235 
1236 int
1238 {
1239  return 0;
1240 }
1241 
1242 void
1244 {
1245 }
1246 
1247 int
1248 SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
1249 {
1250  return SDL_Unsupported();
1251 }
1252 
1253 int
1254 SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1255 {
1256  return SDL_Unsupported();
1257 }
1258 
1259 void
1260 SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
1261 {
1262 }
1263 
1264 void
1265 SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
1266 {
1267 }
1268 
1269 void
1271 {
1272 }
1273 
1274 #endif /* SDL_JOYSTICK_DINPUT */
1275 
1276 /* vi: set ts=4 sw=4 expandtab: */
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:418
SYS_Joystick
JoyStick_DeviceData * SYS_Joystick
SDL_ShouldIgnoreJoystick
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
Definition: SDL_joystick.c:1698
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
JoyStick_DeviceData::dxdevice
DIDEVICEINSTANCE dxdevice
Definition: SDL_windowsjoystick_c.h:39
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
SDL_MAX_RUMBLE_DURATION_MS
#define SDL_MAX_RUMBLE_DURATION_MS
Definition: SDL_sysjoystick.h:143
SDL_XINPUT_Enabled
SDL_bool SDL_XINPUT_Enabled(void)
Definition: SDL_xinputjoystick.c:532
SDL_strlcpy
#define SDL_strlcpy
Definition: SDL_dynapi_overrides.h:394
SDL_GetCustomJoystickName
const char * SDL_GetCustomJoystickName(Uint16 vendor, Uint16 product)
Definition: SDL_joystick.c:1386
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
AXIS
@ AXIS
Definition: SDL_windowsjoystick_c.h:49
in
GLuint in
Definition: SDL_opengl_glext.h:7943
if
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
Definition: pixman-arm-neon-asm.h:469
SDL_HAT_CENTERED
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:339
NULL
#define NULL
Definition: begin_code.h:167
SDL_HAT_DOWN
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:342
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1112
SDL_qsort
#define SDL_qsort
Definition: SDL_dynapi_overrides.h:380
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:419
WINDOWS_AddJoystickDevice
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
JoyStick_DeviceData::guid
SDL_JoystickGUID guid
Definition: SDL_windowsjoystick_c.h:32
DIDEVICEINSTANCE
Definition: SDL_directx.h:106
HIDAPI_IsDevicePresent
SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
JoyStick_DeviceData
Definition: SDL_windowsjoystick_c.h:31
num
GLuint num
Definition: SDL_opengl_glext.h:4959
SDL_DINPUT_JoystickInit
int SDL_DINPUT_JoystickInit(void)
Definition: SDL_dinputjoystick.c:1237
SDL_JoystickGUID::data
Uint8 data[16]
Definition: SDL_joystick.h:71
a
GLboolean GLboolean GLboolean GLboolean a
Definition: SDL_opengl_glext.h:1112
SDL_GetJoystickGameControllerType
SDL_GameControllerType SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
Definition: SDL_joystick.c:1409
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_zeroa
#define SDL_zeroa(x)
Definition: SDL_stdinc.h:420
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:235
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9435
input_t::type
Type type
Definition: SDL_windowsjoystick_c.h:59
SDL_DINPUT_JoystickClose
void SDL_DINPUT_JoystickClose(SDL_Joystick *joystick)
Definition: SDL_dinputjoystick.c:1265
n
GLdouble n
Definition: SDL_opengl_glext.h:1955
DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION
Definition: SDL_directx.h:95
SDL_PrivateJoystickAxis
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:1023
input_t::num
Uint8 num
Definition: SDL_windowsjoystick_c.h:62
SDL_windowsjoystick_c.h
SDL_PRESSED
#define SDL_PRESSED
Definition: SDL_events.h:50
Sint16
int16_t Sint16
Definition: SDL_stdinc.h:185
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
SDL_JOYSTICK_AXIS_MIN
#define SDL_JOYSTICK_AXIS_MIN
Definition: SDL_joystick.h:312
WIN_CoUninitialize
void WIN_CoUninitialize(void)
SDL_memcmp
#define SDL_memcmp
Definition: SDL_dynapi_overrides.h:389
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SUCCEEDED
#define SUCCEEDED(x)
Definition: SDL_directx.h:51
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:663
input_t::ofs
DWORD ofs
Definition: SDL_windowsjoystick_c.h:56
SDL_PrivateJoystickButton
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:1162
SDL_wcscmp
#define SDL_wcscmp
Definition: SDL_dynapi_overrides.h:629
SDL_dinputjoystick_c.h
SDL_HAT_LEFT
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:343
SDL_DINPUT_JoystickUpdate
void SDL_DINPUT_JoystickUpdate(SDL_Joystick *joystick)
Definition: SDL_dinputjoystick.c:1260
SDL_wcslcpy
#define SDL_wcslcpy
Definition: SDL_dynapi_overrides.h:391
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_JOYSTICK_AXIS_MAX
#define SDL_JOYSTICK_AXIS_MAX
Definition: SDL_joystick.h:311
SDL_HARDWARE_BUS_USB
#define SDL_HARDWARE_BUS_USB
Definition: SDL_sysjoystick.h:82
SDL_sscanf
#define SDL_sscanf
Definition: SDL_dynapi_overrides.h:39
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
WIN_CoInitialize
HRESULT WIN_CoInitialize(void)
SDL_PrivateJoystickHat
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:1086
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_DINPUT_JoystickQuit
void SDL_DINPUT_JoystickQuit(void)
Definition: SDL_dinputjoystick.c:1270
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_DINPUT_JoystickRumble
int SDL_DINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
Definition: SDL_dinputjoystick.c:1254
SDL_xinputjoystick_c.h
SDL_HAT_RIGHT
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:341
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:701
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_GameControllerType
SDL_GameControllerType
Definition: SDL_gamecontroller.h:61
JoyStick_DeviceData::hidPath
WCHAR hidPath[MAX_PATH]
Definition: SDL_windowsjoystick_c.h:40
WIN_StringToUTF8
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:397
FAILED
#define FAILED(x)
Definition: SDL_directx.h:54
JoyStick_DeviceData::joystickname
char * joystickname
Definition: SDL_windowsjoystick_c.h:33
HAT
@ HAT
Definition: SDL_windowsjoystick_c.h:50
SDL_wcsstr
#define SDL_wcsstr
Definition: SDL_dynapi_overrides.h:732
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_HAT_UP
#define SDL_HAT_UP
Definition: SDL_joystick.h:340
SDL_CONTROLLER_TYPE_XBOX360
@ SDL_CONTROLLER_TYPE_XBOX360
Definition: SDL_gamecontroller.h:63
SDL_HARDWARE_BUS_BLUETOOTH
#define SDL_HARDWARE_BUS_BLUETOOTH
Definition: SDL_sysjoystick.h:83
j
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_Unsupported
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_DINPUT_JoystickOpen
int SDL_DINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice)
Definition: SDL_dinputjoystick.c:1248
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
FIELD_OFFSET
#define FIELD_OFFSET(type, field)
Definition: SDL_directx.h:87
SDL_strstr
#define SDL_strstr
Definition: SDL_dynapi_overrides.h:403
device
static SDL_AudioDeviceID device
Definition: loopwave.c:37
input_t
Definition: SDL_windowsjoystick_c.h:54
SDL_CONTROLLER_TYPE_XBOXONE
@ SDL_CONTROLLER_TYPE_XBOXONE
Definition: SDL_gamecontroller.h:64
BUTTON
@ BUTTON
Definition: SDL_windowsjoystick_c.h:48
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
state
struct xkb_state * state
Definition: SDL_waylandsym.h:114
JoyStick_DeviceData::pNext
struct JoyStick_DeviceData * pNext
Definition: SDL_windowsjoystick_c.h:41
SDL_DINPUT_JoystickDetect
void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
Definition: SDL_dinputjoystick.c:1243
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
MAX_INPUTS
#define MAX_INPUTS
Definition: SDL_windowsjoystick_c.h:28