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