SDL  2.0
SDL_dinputjoystick.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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 static SDL_bool
239 SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
240 {
241  static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
242  static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
243  static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
244  static GUID IID_XOneWiredGamepad = { MAKELONG(0x045E, 0x02FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
245  static GUID IID_XOneWirelessGamepad = { MAKELONG(0x045E, 0x02DD), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
246  static GUID IID_XOneNewWirelessGamepad = { MAKELONG(0x045E, 0x02D1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
247  static GUID IID_XOneSWirelessGamepad = { MAKELONG(0x045E, 0x02EA), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
248  static GUID IID_XOneSBluetoothGamepad = { MAKELONG(0x045E, 0x02E0), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
249  static GUID IID_XOneEliteWirelessGamepad = { MAKELONG(0x045E, 0x02E3), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
250 
251  static const GUID *s_XInputProductGUID[] = {
252  &IID_ValveStreamingGamepad,
253  &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
254  &IID_X360WirelessGamepad, /* Microsoft's wireless X360 controller for Windows. */
255  &IID_XOneWiredGamepad, /* Microsoft's wired Xbox One controller for Windows. */
256  &IID_XOneWirelessGamepad, /* Microsoft's wireless Xbox One controller for Windows. */
257  &IID_XOneNewWirelessGamepad, /* Microsoft's updated wireless Xbox One controller (w/ 3.5 mm jack) for Windows. */
258  &IID_XOneSWirelessGamepad, /* Microsoft's wireless Xbox One S controller for Windows. */
259  &IID_XOneSBluetoothGamepad, /* Microsoft's Bluetooth Xbox One S controller for Windows. */
260  &IID_XOneEliteWirelessGamepad /* Microsoft's wireless Xbox One Elite controller for Windows. */
261  };
262 
263  size_t iDevice;
264  UINT i;
265 
266  if (!SDL_XINPUT_Enabled()) {
267  return SDL_FALSE;
268  }
269 
270  /* Check for well known XInput device GUIDs */
271  /* 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. */
272  for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
273  if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
274  return SDL_TRUE;
275  }
276  }
277 
278  /* Go through RAWINPUT (WinXP and later) to find HID devices. */
279  /* Cache this if we end up using it. */
280  if (SDL_RawDevList == NULL) {
281  if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
282  return SDL_FALSE; /* oh well. */
283  }
284 
285  SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
286  if (SDL_RawDevList == NULL) {
287  SDL_OutOfMemory();
288  return SDL_FALSE;
289  }
290 
291  if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
292  SDL_free(SDL_RawDevList);
293  SDL_RawDevList = NULL;
294  return SDL_FALSE; /* oh well. */
295  }
296  }
297 
298  for (i = 0; i < SDL_RawDevListCount; i++) {
299  RID_DEVICE_INFO rdi;
300  char devName[128];
301  UINT rdiSize = sizeof(rdi);
302  UINT nameSize = SDL_arraysize(devName);
303 
304  rdi.cbSize = sizeof(rdi);
305  if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
306  (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
307  (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
308  (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
309  (SDL_strstr(devName, "IG_") != NULL)) {
310  return SDL_TRUE;
311  }
312  }
313 
314  return SDL_FALSE;
315 }
316 
317 void FreeRumbleEffectData(DIEFFECT *effect)
318 {
319  if (!effect) {
320  return;
321  }
322  SDL_free(effect->rgdwAxes);
323  SDL_free(effect->rglDirection);
324  SDL_free(effect->lpvTypeSpecificParams);
325  SDL_free(effect);
326 }
327 
328 DIEFFECT *CreateRumbleEffectData(Sint16 magnitude, Uint32 duration_ms)
329 {
330  DIEFFECT *effect;
331  DIPERIODIC *periodic;
332 
333  /* Create the effect */
334  effect = (DIEFFECT *)SDL_calloc(1, sizeof(*effect));
335  if (!effect) {
336  return NULL;
337  }
338  effect->dwSize = sizeof(*effect);
339  effect->dwGain = 10000;
340  effect->dwFlags = DIEFF_OBJECTOFFSETS;
341  effect->dwDuration = duration_ms * 1000; /* In microseconds. */
342  effect->dwTriggerButton = DIEB_NOTRIGGER;
343 
344  effect->cAxes = 2;
345  effect->rgdwAxes = (DWORD *)SDL_calloc(effect->cAxes, sizeof(DWORD));
346  if (!effect->rgdwAxes) {
347  FreeRumbleEffectData(effect);
348  return NULL;
349  }
350 
351  effect->rglDirection = (LONG *)SDL_calloc(effect->cAxes, sizeof(LONG));
352  if (!effect->rglDirection) {
353  FreeRumbleEffectData(effect);
354  return NULL;
355  }
356  effect->dwFlags |= DIEFF_CARTESIAN;
357 
358  periodic = (DIPERIODIC *)SDL_calloc(1, sizeof(*periodic));
359  if (!periodic) {
360  FreeRumbleEffectData(effect);
361  return NULL;
362  }
363  periodic->dwMagnitude = CONVERT_MAGNITUDE(magnitude);
364  periodic->dwPeriod = 1000000;
365 
366  effect->cbTypeSpecificParams = sizeof(*periodic);
367  effect->lpvTypeSpecificParams = periodic;
368 
369  return effect;
370 }
371 
372 int
374 {
375  HRESULT result;
376  HINSTANCE instance;
377 
379  if (FAILED(result)) {
380  return SetDIerror("CoInitialize", result);
381  }
382 
383  coinitialized = SDL_TRUE;
384 
385  result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
386  &IID_IDirectInput8, (LPVOID)&dinput);
387 
388  if (FAILED(result)) {
389  return SetDIerror("CoCreateInstance", result);
390  }
391 
392  /* Because we used CoCreateInstance, we need to Initialize it, first. */
393  instance = GetModuleHandle(NULL);
394  if (instance == NULL) {
395  return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
396  }
397  result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
398 
399  if (FAILED(result)) {
400  return SetDIerror("IDirectInput::Initialize", result);
401  }
402  return 0;
403 }
404 
405 /* helper function for direct input, gets called for each connected joystick */
406 static BOOL CALLBACK
407 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
408 {
409  JoyStick_DeviceData *pNewJoystick;
410  JoyStick_DeviceData *pPrevJoystick = NULL;
411  const DWORD devtype = (pdidInstance->dwDevType & 0xFF);
412  Uint16 *guid16;
413  Uint16 vendor = 0;
414  Uint16 product = 0;
415  Uint16 version = 0;
416  WCHAR hidPath[MAX_PATH];
417 
418  if (devtype == DI8DEVTYPE_SUPPLEMENTAL) {
419  /* Add any supplemental devices that should be ignored here */
420 #define MAKE_TABLE_ENTRY(VID, PID) ((((DWORD)PID)<<16)|VID)
421  static DWORD ignored_devices[] = {
422  MAKE_TABLE_ENTRY(0, 0)
423  };
424 #undef MAKE_TABLE_ENTRY
425  unsigned int i;
426 
427  for (i = 0; i < SDL_arraysize(ignored_devices); ++i) {
428  if (pdidInstance->guidProduct.Data1 == ignored_devices[i]) {
429  return DIENUM_CONTINUE;
430  }
431  }
432  }
433 
434  if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
435  return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
436  }
437 
438  {
439  HRESULT result;
440  LPDIRECTINPUTDEVICE8 device;
441  LPDIRECTINPUTDEVICE8 InputDevice;
442  DIPROPGUIDANDPATH dipdw2;
443 
444  result = IDirectInput8_CreateDevice(dinput, &(pdidInstance->guidInstance), &device, NULL);
445  if (FAILED(result)) {
446  return DIENUM_CONTINUE; /* better luck next time? */
447  }
448 
449  /* Now get the IDirectInputDevice8 interface, instead. */
450  result = IDirectInputDevice8_QueryInterface(device, &IID_IDirectInputDevice8, (LPVOID *)&InputDevice);
451  /* We are done with this object. Use the stored one from now on. */
452  IDirectInputDevice8_Release(device);
453  if (FAILED(result)) {
454  return DIENUM_CONTINUE; /* better luck next time? */
455  }
456  dipdw2.diph.dwSize = sizeof(dipdw2);
457  dipdw2.diph.dwHeaderSize = sizeof(dipdw2.diph);
458  dipdw2.diph.dwObj = 0; // device property
459  dipdw2.diph.dwHow = DIPH_DEVICE;
460 
461  result = IDirectInputDevice8_GetProperty(InputDevice, DIPROP_GUIDANDPATH, &dipdw2.diph);
462  IDirectInputDevice8_Release(InputDevice);
463  if (FAILED(result)) {
464  return DIENUM_CONTINUE; /* better luck next time? */
465  }
466 
467  /* Get device path, compare that instead of GUID, additionally update GUIDs of joysticks with matching paths, in case they're not open yet. */
468  SDL_wcslcpy(hidPath, dipdw2.wszPath, SDL_arraysize(hidPath));
469  }
470 
471  pNewJoystick = *(JoyStick_DeviceData **)pContext;
472  while (pNewJoystick) {
473  if (SDL_wcscmp(pNewJoystick->hidPath, hidPath) == 0) {
474  /* if we are replacing the front of the list then update it */
475  if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
476  *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
477  } else if (pPrevJoystick) {
478  pPrevJoystick->pNext = pNewJoystick->pNext;
479  }
480 
481  // Update with new guid/etc, if it has changed
482  pNewJoystick->dxdevice = *pdidInstance;
483 
484  pNewJoystick->pNext = SYS_Joystick;
485  SYS_Joystick = pNewJoystick;
486 
487  return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
488  }
489 
490  pPrevJoystick = pNewJoystick;
491  pNewJoystick = pNewJoystick->pNext;
492  }
493 
494  pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
495  if (!pNewJoystick) {
496  return DIENUM_CONTINUE; /* better luck next time? */
497  }
498 
499  SDL_zerop(pNewJoystick);
500  SDL_wcslcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath));
501  pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
502  if (!pNewJoystick->joystickname) {
503  SDL_free(pNewJoystick);
504  return DIENUM_CONTINUE; /* better luck next time? */
505  }
506 
507  SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
508  sizeof(DIDEVICEINSTANCE));
509 
510  SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
511 
512  guid16 = (Uint16 *)pNewJoystick->guid.data;
513  if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
514  vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
515  product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
516  version = 0;
517 
518  *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
519  *guid16++ = 0;
520  *guid16++ = SDL_SwapLE16(vendor);
521  *guid16++ = 0;
522  *guid16++ = SDL_SwapLE16(product);
523  *guid16++ = 0;
524  *guid16++ = SDL_SwapLE16(version);
525  *guid16++ = 0;
526  } else {
528  *guid16++ = 0;
529  SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
530  }
531 
532  if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
533  SDL_free(pNewJoystick);
534  return DIENUM_CONTINUE;
535  }
536 
537 #ifdef SDL_JOYSTICK_HIDAPI
538  if (HIDAPI_IsDevicePresent(vendor, product, 0)) {
539  /* The HIDAPI driver is taking care of this device */
540  SDL_free(pNewJoystick);
541  return DIENUM_CONTINUE;
542  }
543 #endif
544 
545  WINDOWS_AddJoystickDevice(pNewJoystick);
546 
547  return DIENUM_CONTINUE; /* get next device, please */
548 }
549 
550 void
552 {
553  IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
554 
555  if (SDL_RawDevList) {
556  SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */
557  SDL_RawDevList = NULL;
558  }
559  SDL_RawDevListCount = 0;
560 }
561 
562 static BOOL CALLBACK
563 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
564 {
565  SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
566  HRESULT result;
567  input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
568 
569  if (dev->dwType & DIDFT_BUTTON) {
570  in->type = BUTTON;
571  in->num = joystick->nbuttons;
572  in->ofs = DIJOFS_BUTTON(in->num);
573  joystick->nbuttons++;
574  } else if (dev->dwType & DIDFT_POV) {
575  in->type = HAT;
576  in->num = joystick->nhats;
577  in->ofs = DIJOFS_POV(in->num);
578  joystick->nhats++;
579  } else if (dev->dwType & DIDFT_AXIS) {
580  DIPROPRANGE diprg;
581  DIPROPDWORD dilong;
582 
583  in->type = AXIS;
584  in->num = joystick->naxes;
585  if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
586  in->ofs = DIJOFS_X;
587  else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
588  in->ofs = DIJOFS_Y;
589  else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
590  in->ofs = DIJOFS_Z;
591  else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
592  in->ofs = DIJOFS_RX;
593  else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
594  in->ofs = DIJOFS_RY;
595  else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
596  in->ofs = DIJOFS_RZ;
597  else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
598  in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
599  ++joystick->hwdata->NumSliders;
600  } else {
601  return DIENUM_CONTINUE; /* not an axis we can grok */
602  }
603 
604  diprg.diph.dwSize = sizeof(diprg);
605  diprg.diph.dwHeaderSize = sizeof(diprg.diph);
606  diprg.diph.dwObj = dev->dwType;
607  diprg.diph.dwHow = DIPH_BYID;
608  diprg.lMin = SDL_JOYSTICK_AXIS_MIN;
609  diprg.lMax = SDL_JOYSTICK_AXIS_MAX;
610 
611  result =
612  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
613  DIPROP_RANGE, &diprg.diph);
614  if (FAILED(result)) {
615  return DIENUM_CONTINUE; /* don't use this axis */
616  }
617 
618  /* Set dead zone to 0. */
619  dilong.diph.dwSize = sizeof(dilong);
620  dilong.diph.dwHeaderSize = sizeof(dilong.diph);
621  dilong.diph.dwObj = dev->dwType;
622  dilong.diph.dwHow = DIPH_BYID;
623  dilong.dwData = 0;
624  result =
625  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
626  DIPROP_DEADZONE, &dilong.diph);
627  if (FAILED(result)) {
628  return DIENUM_CONTINUE; /* don't use this axis */
629  }
630 
631  joystick->naxes++;
632  } else {
633  /* not supported at this time */
634  return DIENUM_CONTINUE;
635  }
636 
637  joystick->hwdata->NumInputs++;
638 
639  if (joystick->hwdata->NumInputs == MAX_INPUTS) {
640  return DIENUM_STOP; /* too many */
641  }
642 
643  return DIENUM_CONTINUE;
644 }
645 
646 /* Sort using the data offset into the DInput struct.
647  * This gives a reasonable ordering for the inputs.
648  */
649 static int
650 SortDevFunc(const void *a, const void *b)
651 {
652  const input_t *inputA = (const input_t*)a;
653  const input_t *inputB = (const input_t*)b;
654 
655  if (inputA->ofs < inputB->ofs)
656  return -1;
657  if (inputA->ofs > inputB->ofs)
658  return 1;
659  return 0;
660 }
661 
662 /* Sort the input objects and recalculate the indices for each input. */
663 static void
664 SortDevObjects(SDL_Joystick *joystick)
665 {
666  input_t *inputs = joystick->hwdata->Inputs;
667  int nButtons = 0;
668  int nHats = 0;
669  int nAxis = 0;
670  int n;
671 
672  SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
673 
674  for (n = 0; n < joystick->hwdata->NumInputs; n++) {
675  switch (inputs[n].type) {
676  case BUTTON:
677  inputs[n].num = nButtons;
678  nButtons++;
679  break;
680 
681  case HAT:
682  inputs[n].num = nHats;
683  nHats++;
684  break;
685 
686  case AXIS:
687  inputs[n].num = nAxis;
688  nAxis++;
689  break;
690  }
691  }
692 }
693 
694 int
695 SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
696 {
697  HRESULT result;
698  LPDIRECTINPUTDEVICE8 device;
699  DIPROPDWORD dipdw;
700 
701  joystick->hwdata->buffered = SDL_TRUE;
702  joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
703 
704  SDL_zero(dipdw);
705  dipdw.diph.dwSize = sizeof(DIPROPDWORD);
706  dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
707 
708  result =
709  IDirectInput8_CreateDevice(dinput,
710  &(joystickdevice->dxdevice.guidInstance), &device, NULL);
711  if (FAILED(result)) {
712  return SetDIerror("IDirectInput::CreateDevice", result);
713  }
714 
715  /* Now get the IDirectInputDevice8 interface, instead. */
716  result = IDirectInputDevice8_QueryInterface(device,
717  &IID_IDirectInputDevice8,
718  (LPVOID *)& joystick->
719  hwdata->InputDevice);
720  /* We are done with this object. Use the stored one from now on. */
721  IDirectInputDevice8_Release(device);
722 
723  if (FAILED(result)) {
724  return SetDIerror("IDirectInputDevice8::QueryInterface", result);
725  }
726 
727  /* Acquire shared access. Exclusive access is required for forces,
728  * though. */
729  result =
730  IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
731  InputDevice, SDL_HelperWindow,
732  DISCL_EXCLUSIVE |
733  DISCL_BACKGROUND);
734  if (FAILED(result)) {
735  return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
736  }
737 
738  /* Use the extended data structure: DIJOYSTATE2. */
739  result =
740  IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
741  &SDL_c_dfDIJoystick2);
742  if (FAILED(result)) {
743  return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
744  }
745 
746  /* Get device capabilities */
747  result =
748  IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
749  &joystick->hwdata->Capabilities);
750  if (FAILED(result)) {
751  return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
752  }
753 
754  /* Force capable? */
755  if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
756  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
757  if (FAILED(result)) {
758  return SetDIerror("IDirectInputDevice8::Acquire", result);
759  }
760 
761  /* reset all actuators. */
762  result =
763  IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
764  InputDevice,
765  DISFFC_RESET);
766 
767  /* Not necessarily supported, ignore if not supported.
768  if (FAILED(result)) {
769  return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
770  }
771  */
772 
773  result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
774 
775  if (FAILED(result)) {
776  return SetDIerror("IDirectInputDevice8::Unacquire", result);
777  }
778 
779  /* Turn on auto-centering for a ForceFeedback device (until told
780  * otherwise). */
781  dipdw.diph.dwObj = 0;
782  dipdw.diph.dwHow = DIPH_DEVICE;
783  dipdw.dwData = DIPROPAUTOCENTER_ON;
784 
785  result =
786  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
787  DIPROP_AUTOCENTER, &dipdw.diph);
788 
789  /* Not necessarily supported, ignore if not supported.
790  if (FAILED(result)) {
791  return SetDIerror("IDirectInputDevice8::SetProperty", result);
792  }
793  */
794  }
795 
796  /* What buttons and axes does it have? */
797  IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
798  EnumDevObjectsCallback, joystick,
799  DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
800 
801  /* Reorder the input objects. Some devices do not report the X axis as
802  * the first axis, for example. */
803  SortDevObjects(joystick);
804 
805  dipdw.diph.dwObj = 0;
806  dipdw.diph.dwHow = DIPH_DEVICE;
807  dipdw.dwData = INPUT_QSIZE;
808 
809  /* Set the buffer size */
810  result =
811  IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
812  DIPROP_BUFFERSIZE, &dipdw.diph);
813 
814  if (result == DI_POLLEDDEVICE) {
815  /* This device doesn't support buffering, so we're forced
816  * to use less reliable polling. */
817  joystick->hwdata->buffered = SDL_FALSE;
818  } else if (FAILED(result)) {
819  return SetDIerror("IDirectInputDevice8::SetProperty", result);
820  }
821  return 0;
822 }
823 
824 static int
825 SDL_DINPUT_JoystickInitRumble(SDL_Joystick * joystick, Sint16 magnitude, Uint32 duration_ms)
826 {
827  HRESULT result;
828 
829  /* Reset and then enable actuators */
830  result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_RESET);
831  if (result == DIERR_INPUTLOST || result == DIERR_NOTEXCLUSIVEACQUIRED) {
832  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
833  if (SUCCEEDED(result)) {
834  result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_RESET);
835  }
836  }
837  if (FAILED(result)) {
838  return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand(DISFFC_RESET)", result);
839  }
840 
841  result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_SETACTUATORSON);
842  if (FAILED(result)) {
843  return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand(DISFFC_SETACTUATORSON)", result);
844  }
845 
846  /* Create the effect */
847  joystick->hwdata->ffeffect = CreateRumbleEffectData(magnitude, duration_ms);
848  if (!joystick->hwdata->ffeffect) {
849  return SDL_OutOfMemory();
850  }
851 
852  result = IDirectInputDevice8_CreateEffect(joystick->hwdata->InputDevice, &GUID_Sine,
853  joystick->hwdata->ffeffect, &joystick->hwdata->ffeffect_ref, NULL);
854  if (FAILED(result)) {
855  return SetDIerror("IDirectInputDevice8::CreateEffect", result);
856  }
857  return 0;
858 }
859 
860 int
861 SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
862 {
863  HRESULT result;
864 
865  /* Scale and average the two rumble strengths */
866  Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
867 
868  if (!(joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK)) {
869  return SDL_Unsupported();
870  }
871 
872  if (joystick->hwdata->ff_initialized) {
873  DIPERIODIC *periodic = ((DIPERIODIC *)joystick->hwdata->ffeffect->lpvTypeSpecificParams);
874  joystick->hwdata->ffeffect->dwDuration = duration_ms * 1000; /* In microseconds. */
875  periodic->dwMagnitude = CONVERT_MAGNITUDE(magnitude);
876 
877  result = IDirectInputEffect_SetParameters(joystick->hwdata->ffeffect_ref, joystick->hwdata->ffeffect, (DIEP_DURATION | DIEP_TYPESPECIFICPARAMS));
878  if (result == DIERR_INPUTLOST) {
879  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
880  if (SUCCEEDED(result)) {
881  result = IDirectInputEffect_SetParameters(joystick->hwdata->ffeffect_ref, joystick->hwdata->ffeffect, (DIEP_DURATION | DIEP_TYPESPECIFICPARAMS));
882  }
883  }
884  if (FAILED(result)) {
885  return SetDIerror("IDirectInputDevice8::SetParameters", result);
886  }
887  } else {
888  if (SDL_DINPUT_JoystickInitRumble(joystick, magnitude, duration_ms) < 0) {
889  return -1;
890  }
891  joystick->hwdata->ff_initialized = SDL_TRUE;
892  }
893 
894  result = IDirectInputEffect_Start(joystick->hwdata->ffeffect_ref, 1, 0);
895  if (result == DIERR_INPUTLOST || result == DIERR_NOTEXCLUSIVEACQUIRED) {
896  result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
897  if (SUCCEEDED(result)) {
898  result = IDirectInputEffect_Start(joystick->hwdata->ffeffect_ref, 1, 0);
899  }
900  }
901  if (FAILED(result)) {
902  return SetDIerror("IDirectInputDevice8::Start", result);
903  }
904  return 0;
905 }
906 
907 static Uint8
908 TranslatePOV(DWORD value)
909 {
910  const int HAT_VALS[] = {
911  SDL_HAT_UP,
915  SDL_HAT_DOWN,
917  SDL_HAT_LEFT,
919  };
920 
921  if (LOWORD(value) == 0xFFFF)
922  return SDL_HAT_CENTERED;
923 
924  /* Round the value up: */
925  value += 4500 / 2;
926  value %= 36000;
927  value /= 4500;
928 
929  if (value >= 8)
930  return SDL_HAT_CENTERED; /* shouldn't happen */
931 
932  return HAT_VALS[value];
933 }
934 
935 static void
936 UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
937 {
938  int i;
939  HRESULT result;
940  DWORD numevents;
941  DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
942 
943  numevents = INPUT_QSIZE;
944  result =
945  IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
946  sizeof(DIDEVICEOBJECTDATA), evtbuf,
947  &numevents, 0);
948  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
949  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
950  result =
951  IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
952  sizeof(DIDEVICEOBJECTDATA),
953  evtbuf, &numevents, 0);
954  }
955 
956  /* Handle the events or punt */
957  if (FAILED(result)) {
958  return;
959  }
960 
961  for (i = 0; i < (int)numevents; ++i) {
962  int j;
963 
964  for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
965  const input_t *in = &joystick->hwdata->Inputs[j];
966 
967  if (evtbuf[i].dwOfs != in->ofs)
968  continue;
969 
970  switch (in->type) {
971  case AXIS:
972  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
973  break;
974  case BUTTON:
975  SDL_PrivateJoystickButton(joystick, in->num,
976  (Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
977  break;
978  case HAT:
979  {
980  Uint8 pos = TranslatePOV(evtbuf[i].dwData);
981  SDL_PrivateJoystickHat(joystick, in->num, pos);
982  }
983  break;
984  }
985  }
986  }
987 }
988 
989 /* Function to update the state of a joystick - called as a device poll.
990  * This function shouldn't update the joystick structure directly,
991  * but instead should call SDL_PrivateJoystick*() to deliver events
992  * and update joystick device state.
993  */
994 static void
995 UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
996 {
997  DIJOYSTATE2 state;
998  HRESULT result;
999  int i;
1000 
1001  result =
1002  IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
1003  sizeof(DIJOYSTATE2), &state);
1004  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1005  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1006  result =
1007  IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
1008  sizeof(DIJOYSTATE2), &state);
1009  }
1010 
1011  if (result != DI_OK) {
1012  return;
1013  }
1014 
1015  /* Set each known axis, button and POV. */
1016  for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
1017  const input_t *in = &joystick->hwdata->Inputs[i];
1018 
1019  switch (in->type) {
1020  case AXIS:
1021  switch (in->ofs) {
1022  case DIJOFS_X:
1023  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
1024  break;
1025  case DIJOFS_Y:
1026  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
1027  break;
1028  case DIJOFS_Z:
1029  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
1030  break;
1031  case DIJOFS_RX:
1032  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
1033  break;
1034  case DIJOFS_RY:
1035  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
1036  break;
1037  case DIJOFS_RZ:
1038  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
1039  break;
1040  case DIJOFS_SLIDER(0):
1041  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
1042  break;
1043  case DIJOFS_SLIDER(1):
1044  SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
1045  break;
1046  }
1047  break;
1048 
1049  case BUTTON:
1050  SDL_PrivateJoystickButton(joystick, in->num,
1051  (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
1052  break;
1053  case HAT:
1054  {
1055  Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
1056  SDL_PrivateJoystickHat(joystick, in->num, pos);
1057  break;
1058  }
1059  }
1060  }
1061 }
1062 
1063 void
1064 SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
1065 {
1066  HRESULT result;
1067 
1068  result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
1069  if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
1070  IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
1071  IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
1072  }
1073 
1074  if (joystick->hwdata->buffered) {
1075  UpdateDINPUTJoystickState_Buffered(joystick);
1076  } else {
1077  UpdateDINPUTJoystickState_Polled(joystick);
1078  }
1079 }
1080 
1081 void
1082 SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
1083 {
1084  if (joystick->hwdata->ffeffect_ref) {
1085  IDirectInputEffect_Unload(joystick->hwdata->ffeffect_ref);
1086  joystick->hwdata->ffeffect_ref = NULL;
1087  }
1088  if (joystick->hwdata->ffeffect) {
1089  FreeRumbleEffectData(joystick->hwdata->ffeffect);
1090  joystick->hwdata->ffeffect = NULL;
1091  }
1092  IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
1093  IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
1094  joystick->hwdata->ff_initialized = SDL_FALSE;
1095 }
1096 
1097 void
1099 {
1100  if (dinput != NULL) {
1101  IDirectInput8_Release(dinput);
1102  dinput = NULL;
1103  }
1104 
1105  if (coinitialized) {
1107  coinitialized = SDL_FALSE;
1108  }
1109 }
1110 
1111 #else /* !SDL_JOYSTICK_DINPUT */
1112 
1114 
1115 int
1117 {
1118  return 0;
1119 }
1120 
1121 void
1123 {
1124 }
1125 
1126 int
1127 SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
1128 {
1129  return SDL_Unsupported();
1130 }
1131 
1132 int
1133 SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
1134 {
1135  return SDL_Unsupported();
1136 }
1137 
1138 void
1139 SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
1140 {
1141 }
1142 
1143 void
1144 SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
1145 {
1146 }
1147 
1148 void
1150 {
1151 }
1152 
1153 #endif /* SDL_JOYSTICK_DINPUT */
1154 
1155 /* vi: set ts=4 sw=4 expandtab: */
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SYS_Joystick
JoyStick_DeviceData * SYS_Joystick
SDL_ShouldIgnoreJoystick
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
Definition: SDL_joystick.c:1359
JoyStick_DeviceData::dxdevice
DIDEVICEINSTANCE dxdevice
Definition: SDL_windowsjoystick_c.h:39
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
SDL_DINPUT_JoystickRumble
int SDL_DINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
Definition: SDL_dinputjoystick.c:1133
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_XINPUT_Enabled
SDL_bool SDL_XINPUT_Enabled(void)
Definition: SDL_xinputjoystick.c:515
SDL_strlcpy
#define SDL_strlcpy
Definition: SDL_dynapi_overrides.h:394
AXIS
@ AXIS
Definition: SDL_windowsjoystick_c.h:49
in
GLuint in
Definition: SDL_opengl_glext.h:7940
SDL_HAT_CENTERED
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:329
NULL
#define NULL
Definition: begin_code.h:167
SDL_HAT_DOWN
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:332
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
SDL_qsort
#define SDL_qsort
Definition: SDL_dynapi_overrides.h:380
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
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
JoyStick_DeviceData
Definition: SDL_windowsjoystick_c.h:30
num
GLuint num
Definition: SDL_opengl_glext.h:4956
SDL_DINPUT_JoystickInit
int SDL_DINPUT_JoystickInit(void)
Definition: SDL_dinputjoystick.c:1116
SDL_JoystickGUID::data
Uint8 data[16]
Definition: SDL_joystick.h:71
a
GLboolean GLboolean GLboolean GLboolean a
Definition: SDL_opengl_glext.h:1109
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:241
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9432
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:1144
n
GLdouble n
Definition: SDL_opengl_glext.h:1952
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:833
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_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_JOYSTICK_AXIS_MIN
#define SDL_JOYSTICK_AXIS_MIN
Definition: SDL_joystick.h:302
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
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:966
SDL_wcscmp
#define SDL_wcscmp
Definition: SDL_dynapi_overrides.h:629
SDL_dinputjoystick_c.h
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
SDL_HAT_LEFT
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:333
SDL_DINPUT_JoystickUpdate
void SDL_DINPUT_JoystickUpdate(SDL_Joystick *joystick)
Definition: SDL_dinputjoystick.c:1139
SDL_wcslcpy
#define SDL_wcslcpy
Definition: SDL_dynapi_overrides.h:391
SDL_JOYSTICK_AXIS_MAX
#define SDL_JOYSTICK_AXIS_MAX
Definition: SDL_joystick.h:301
SDL_HARDWARE_BUS_USB
#define SDL_HARDWARE_BUS_USB
Definition: SDL_sysjoystick.h:86
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:890
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_DINPUT_JoystickQuit
void SDL_DINPUT_JoystickQuit(void)
Definition: SDL_dinputjoystick.c:1149
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_xinputjoystick_c.h
SDL_HAT_RIGHT
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:331
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
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
JoyStick_DeviceData::hidPath
WCHAR hidPath[MAX_PATH]
Definition: SDL_windowsjoystick_c.h:40
WIN_StringToUTF8
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
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_HAT_UP
#define SDL_HAT_UP
Definition: SDL_joystick.h:330
SDL_HARDWARE_BUS_BLUETOOTH
#define SDL_HARDWARE_BUS_BLUETOOTH
Definition: SDL_sysjoystick.h:87
HIDAPI_IsDevicePresent
SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version)
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:1127
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:53
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:113
JoyStick_DeviceData::pNext
struct JoyStick_DeviceData * pNext
Definition: SDL_windowsjoystick_c.h:41
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
SDL_DINPUT_JoystickDetect
void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
Definition: SDL_dinputjoystick.c:1122
MAX_INPUTS
#define MAX_INPUTS
Definition: SDL_windowsjoystick_c.h:28
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179