SDL_dinputjoystick.c (38655B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 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#include "SDL_windowsjoystick_c.h" 25#include "SDL_dinputjoystick_c.h" 26#include "SDL_xinputjoystick_c.h" 27 28 29#if SDL_JOYSTICK_DINPUT 30 31#ifndef DIDFT_OPTIONAL 32#define DIDFT_OPTIONAL 0x80000000 33#endif 34 35#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */ 36#define AXIS_MIN -32768 /* minimum value for axis coordinate */ 37#define AXIS_MAX 32767 /* maximum value for axis coordinate */ 38#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */ 39 40/* external variables referenced. */ 41extern HWND SDL_HelperWindow; 42 43/* local variables */ 44static SDL_bool coinitialized = SDL_FALSE; 45static LPDIRECTINPUT8 dinput = NULL; 46static PRAWINPUTDEVICELIST SDL_RawDevList = NULL; 47static UINT SDL_RawDevListCount = 0; 48 49/* Taken from Wine - Thanks! */ 50static DIOBJECTDATAFORMAT dfDIJoystick2[] = { 51 { &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 52 { &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 53 { &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 54 { &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 55 { &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 56 { &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 57 { &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 58 { &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 59 { &GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 }, 60 { &GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 }, 61 { &GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 }, 62 { &GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 }, 63 { NULL, DIJOFS_BUTTON(0), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 64 { NULL, DIJOFS_BUTTON(1), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 65 { NULL, DIJOFS_BUTTON(2), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 66 { NULL, DIJOFS_BUTTON(3), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 67 { NULL, DIJOFS_BUTTON(4), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 68 { NULL, DIJOFS_BUTTON(5), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 69 { NULL, DIJOFS_BUTTON(6), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 70 { NULL, DIJOFS_BUTTON(7), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 71 { NULL, DIJOFS_BUTTON(8), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 72 { NULL, DIJOFS_BUTTON(9), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 73 { NULL, DIJOFS_BUTTON(10), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 74 { NULL, DIJOFS_BUTTON(11), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 75 { NULL, DIJOFS_BUTTON(12), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 76 { NULL, DIJOFS_BUTTON(13), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 77 { NULL, DIJOFS_BUTTON(14), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 78 { NULL, DIJOFS_BUTTON(15), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 79 { NULL, DIJOFS_BUTTON(16), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 80 { NULL, DIJOFS_BUTTON(17), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 81 { NULL, DIJOFS_BUTTON(18), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 82 { NULL, DIJOFS_BUTTON(19), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 83 { NULL, DIJOFS_BUTTON(20), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 84 { NULL, DIJOFS_BUTTON(21), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 85 { NULL, DIJOFS_BUTTON(22), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 86 { NULL, DIJOFS_BUTTON(23), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 87 { NULL, DIJOFS_BUTTON(24), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 88 { NULL, DIJOFS_BUTTON(25), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 89 { NULL, DIJOFS_BUTTON(26), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 90 { NULL, DIJOFS_BUTTON(27), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 91 { NULL, DIJOFS_BUTTON(28), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 92 { NULL, DIJOFS_BUTTON(29), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 93 { NULL, DIJOFS_BUTTON(30), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 94 { NULL, DIJOFS_BUTTON(31), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 95 { NULL, DIJOFS_BUTTON(32), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 96 { NULL, DIJOFS_BUTTON(33), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 97 { NULL, DIJOFS_BUTTON(34), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 98 { NULL, DIJOFS_BUTTON(35), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 99 { NULL, DIJOFS_BUTTON(36), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 100 { NULL, DIJOFS_BUTTON(37), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 101 { NULL, DIJOFS_BUTTON(38), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 102 { NULL, DIJOFS_BUTTON(39), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 103 { NULL, DIJOFS_BUTTON(40), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 104 { NULL, DIJOFS_BUTTON(41), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 105 { NULL, DIJOFS_BUTTON(42), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 106 { NULL, DIJOFS_BUTTON(43), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 107 { NULL, DIJOFS_BUTTON(44), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 108 { NULL, DIJOFS_BUTTON(45), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 109 { NULL, DIJOFS_BUTTON(46), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 110 { NULL, DIJOFS_BUTTON(47), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 111 { NULL, DIJOFS_BUTTON(48), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 112 { NULL, DIJOFS_BUTTON(49), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 113 { NULL, DIJOFS_BUTTON(50), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 114 { NULL, DIJOFS_BUTTON(51), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 115 { NULL, DIJOFS_BUTTON(52), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 116 { NULL, DIJOFS_BUTTON(53), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 117 { NULL, DIJOFS_BUTTON(54), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 118 { NULL, DIJOFS_BUTTON(55), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 119 { NULL, DIJOFS_BUTTON(56), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 120 { NULL, DIJOFS_BUTTON(57), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 121 { NULL, DIJOFS_BUTTON(58), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 122 { NULL, DIJOFS_BUTTON(59), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 123 { NULL, DIJOFS_BUTTON(60), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 124 { NULL, DIJOFS_BUTTON(61), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 125 { NULL, DIJOFS_BUTTON(62), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 126 { NULL, DIJOFS_BUTTON(63), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 127 { NULL, DIJOFS_BUTTON(64), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 128 { NULL, DIJOFS_BUTTON(65), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 129 { NULL, DIJOFS_BUTTON(66), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 130 { NULL, DIJOFS_BUTTON(67), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 131 { NULL, DIJOFS_BUTTON(68), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 132 { NULL, DIJOFS_BUTTON(69), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 133 { NULL, DIJOFS_BUTTON(70), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 134 { NULL, DIJOFS_BUTTON(71), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 135 { NULL, DIJOFS_BUTTON(72), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 136 { NULL, DIJOFS_BUTTON(73), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 137 { NULL, DIJOFS_BUTTON(74), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 138 { NULL, DIJOFS_BUTTON(75), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 139 { NULL, DIJOFS_BUTTON(76), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 140 { NULL, DIJOFS_BUTTON(77), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 141 { NULL, DIJOFS_BUTTON(78), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 142 { NULL, DIJOFS_BUTTON(79), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 143 { NULL, DIJOFS_BUTTON(80), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 144 { NULL, DIJOFS_BUTTON(81), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 145 { NULL, DIJOFS_BUTTON(82), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 146 { NULL, DIJOFS_BUTTON(83), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 147 { NULL, DIJOFS_BUTTON(84), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 148 { NULL, DIJOFS_BUTTON(85), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 149 { NULL, DIJOFS_BUTTON(86), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 150 { NULL, DIJOFS_BUTTON(87), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 151 { NULL, DIJOFS_BUTTON(88), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 152 { NULL, DIJOFS_BUTTON(89), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 153 { NULL, DIJOFS_BUTTON(90), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 154 { NULL, DIJOFS_BUTTON(91), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 155 { NULL, DIJOFS_BUTTON(92), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 156 { NULL, DIJOFS_BUTTON(93), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 157 { NULL, DIJOFS_BUTTON(94), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 158 { NULL, DIJOFS_BUTTON(95), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 159 { NULL, DIJOFS_BUTTON(96), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 160 { NULL, DIJOFS_BUTTON(97), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 161 { NULL, DIJOFS_BUTTON(98), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 162 { NULL, DIJOFS_BUTTON(99), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 163 { NULL, DIJOFS_BUTTON(100), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 164 { NULL, DIJOFS_BUTTON(101), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 165 { NULL, DIJOFS_BUTTON(102), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 166 { NULL, DIJOFS_BUTTON(103), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 167 { NULL, DIJOFS_BUTTON(104), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 168 { NULL, DIJOFS_BUTTON(105), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 169 { NULL, DIJOFS_BUTTON(106), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 170 { NULL, DIJOFS_BUTTON(107), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 171 { NULL, DIJOFS_BUTTON(108), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 172 { NULL, DIJOFS_BUTTON(109), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 173 { NULL, DIJOFS_BUTTON(110), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 174 { NULL, DIJOFS_BUTTON(111), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 175 { NULL, DIJOFS_BUTTON(112), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 176 { NULL, DIJOFS_BUTTON(113), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 177 { NULL, DIJOFS_BUTTON(114), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 178 { NULL, DIJOFS_BUTTON(115), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 179 { NULL, DIJOFS_BUTTON(116), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 180 { NULL, DIJOFS_BUTTON(117), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 181 { NULL, DIJOFS_BUTTON(118), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 182 { NULL, DIJOFS_BUTTON(119), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 183 { NULL, DIJOFS_BUTTON(120), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 184 { NULL, DIJOFS_BUTTON(121), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 185 { NULL, DIJOFS_BUTTON(122), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 186 { NULL, DIJOFS_BUTTON(123), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 187 { NULL, DIJOFS_BUTTON(124), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 188 { NULL, DIJOFS_BUTTON(125), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 189 { NULL, DIJOFS_BUTTON(126), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 190 { NULL, DIJOFS_BUTTON(127), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 }, 191 { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 192 { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 193 { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 194 { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 195 { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 196 { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 197 { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 198 { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 199 { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 200 { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 201 { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 202 { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 203 { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 204 { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 205 { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 206 { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 207 { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 208 { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 209 { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 210 { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 211 { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 212 { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 213 { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 214 { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 }, 215}; 216 217const DIDATAFORMAT c_dfDIJoystick2 = { 218 sizeof(DIDATAFORMAT), 219 sizeof(DIOBJECTDATAFORMAT), 220 DIDF_ABSAXIS, 221 sizeof(DIJOYSTATE2), 222 SDL_arraysize(dfDIJoystick2), 223 dfDIJoystick2 224}; 225 226/* Convert a DirectInput return code to a text message */ 227static int 228SetDIerror(const char *function, HRESULT code) 229{ 230 /* 231 return SDL_SetError("%s() [%s]: %s", function, 232 DXGetErrorString9A(code), DXGetErrorDescription9A(code)); 233 */ 234 return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code); 235} 236 237static SDL_bool 238SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput) 239{ 240 static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } }; 241 static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } }; 242 static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } }; 243 244 static const GUID *s_XInputProductGUID[] = { 245 &IID_ValveStreamingGamepad, 246 &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */ 247 &IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */ 248 }; 249 250 size_t iDevice; 251 UINT i; 252 253 if (!SDL_XINPUT_Enabled()) { 254 return SDL_FALSE; 255 } 256 257 /* Check for well known XInput device GUIDs */ 258 /* 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. */ 259 for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) { 260 if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) { 261 return SDL_TRUE; 262 } 263 } 264 265 /* Go through RAWINPUT (WinXP and later) to find HID devices. */ 266 /* Cache this if we end up using it. */ 267 if (SDL_RawDevList == NULL) { 268 if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) { 269 return SDL_FALSE; /* oh well. */ 270 } 271 272 SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount); 273 if (SDL_RawDevList == NULL) { 274 SDL_OutOfMemory(); 275 return SDL_FALSE; 276 } 277 278 if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) { 279 SDL_free(SDL_RawDevList); 280 SDL_RawDevList = NULL; 281 return SDL_FALSE; /* oh well. */ 282 } 283 } 284 285 for (i = 0; i < SDL_RawDevListCount; i++) { 286 RID_DEVICE_INFO rdi; 287 char devName[128]; 288 UINT rdiSize = sizeof(rdi); 289 UINT nameSize = SDL_arraysize(devName); 290 291 rdi.cbSize = sizeof(rdi); 292 if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) && 293 (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) && 294 (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) && 295 (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) && 296 (SDL_strstr(devName, "IG_") != NULL)) { 297 return SDL_TRUE; 298 } 299 } 300 301 return SDL_FALSE; 302} 303 304int 305SDL_DINPUT_JoystickInit(void) 306{ 307 HRESULT result; 308 HINSTANCE instance; 309 310 result = WIN_CoInitialize(); 311 if (FAILED(result)) { 312 return SetDIerror("CoInitialize", result); 313 } 314 315 coinitialized = SDL_TRUE; 316 317 result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER, 318 &IID_IDirectInput8, (LPVOID)&dinput); 319 320 if (FAILED(result)) { 321 return SetDIerror("CoCreateInstance", result); 322 } 323 324 /* Because we used CoCreateInstance, we need to Initialize it, first. */ 325 instance = GetModuleHandle(NULL); 326 if (instance == NULL) { 327 return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError()); 328 } 329 result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION); 330 331 if (FAILED(result)) { 332 return SetDIerror("IDirectInput::Initialize", result); 333 } 334 return 0; 335} 336 337/* helper function for direct input, gets called for each connected joystick */ 338static BOOL CALLBACK 339EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) 340{ 341 JoyStick_DeviceData *pNewJoystick; 342 JoyStick_DeviceData *pPrevJoystick = NULL; 343 344 if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) { 345 return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */ 346 } 347 348 pNewJoystick = *(JoyStick_DeviceData **)pContext; 349 while (pNewJoystick) { 350 if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) { 351 /* if we are replacing the front of the list then update it */ 352 if (pNewJoystick == *(JoyStick_DeviceData **)pContext) { 353 *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext; 354 } else if (pPrevJoystick) { 355 pPrevJoystick->pNext = pNewJoystick->pNext; 356 } 357 358 pNewJoystick->pNext = SYS_Joystick; 359 SYS_Joystick = pNewJoystick; 360 361 return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */ 362 } 363 364 pPrevJoystick = pNewJoystick; 365 pNewJoystick = pNewJoystick->pNext; 366 } 367 368 pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData)); 369 if (!pNewJoystick) { 370 return DIENUM_CONTINUE; /* better luck next time? */ 371 } 372 373 SDL_zerop(pNewJoystick); 374 pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName); 375 if (!pNewJoystick->joystickname) { 376 SDL_free(pNewJoystick); 377 return DIENUM_CONTINUE; /* better luck next time? */ 378 } 379 380 SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance, 381 sizeof(DIDEVICEINSTANCE)); 382 383 SDL_memcpy(&pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid)); 384 SDL_SYS_AddJoystickDevice(pNewJoystick); 385 386 return DIENUM_CONTINUE; /* get next device, please */ 387} 388 389void 390SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext) 391{ 392 IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY); 393 394 if (SDL_RawDevList) { 395 SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */ 396 SDL_RawDevList = NULL; 397 } 398 SDL_RawDevListCount = 0; 399} 400 401static BOOL CALLBACK 402EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) 403{ 404 SDL_Joystick *joystick = (SDL_Joystick *)pvRef; 405 HRESULT result; 406 input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; 407 408 if (dev->dwType & DIDFT_BUTTON) { 409 in->type = BUTTON; 410 in->num = joystick->nbuttons; 411 in->ofs = DIJOFS_BUTTON(in->num); 412 joystick->nbuttons++; 413 } else if (dev->dwType & DIDFT_POV) { 414 in->type = HAT; 415 in->num = joystick->nhats; 416 in->ofs = DIJOFS_POV(in->num); 417 joystick->nhats++; 418 } else if (dev->dwType & DIDFT_AXIS) { 419 DIPROPRANGE diprg; 420 DIPROPDWORD dilong; 421 422 in->type = AXIS; 423 in->num = joystick->naxes; 424 if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType))) 425 in->ofs = DIJOFS_X; 426 else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType))) 427 in->ofs = DIJOFS_Y; 428 else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType))) 429 in->ofs = DIJOFS_Z; 430 else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType))) 431 in->ofs = DIJOFS_RX; 432 else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType))) 433 in->ofs = DIJOFS_RY; 434 else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType))) 435 in->ofs = DIJOFS_RZ; 436 else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) { 437 in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders); 438 ++joystick->hwdata->NumSliders; 439 } else { 440 return DIENUM_CONTINUE; /* not an axis we can grok */ 441 } 442 443 diprg.diph.dwSize = sizeof(diprg); 444 diprg.diph.dwHeaderSize = sizeof(diprg.diph); 445 diprg.diph.dwObj = dev->dwType; 446 diprg.diph.dwHow = DIPH_BYID; 447 diprg.lMin = AXIS_MIN; 448 diprg.lMax = AXIS_MAX; 449 450 result = 451 IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice, 452 DIPROP_RANGE, &diprg.diph); 453 if (FAILED(result)) { 454 return DIENUM_CONTINUE; /* don't use this axis */ 455 } 456 457 /* Set dead zone to 0. */ 458 dilong.diph.dwSize = sizeof(dilong); 459 dilong.diph.dwHeaderSize = sizeof(dilong.diph); 460 dilong.diph.dwObj = dev->dwType; 461 dilong.diph.dwHow = DIPH_BYID; 462 dilong.dwData = 0; 463 result = 464 IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice, 465 DIPROP_DEADZONE, &dilong.diph); 466 if (FAILED(result)) { 467 return DIENUM_CONTINUE; /* don't use this axis */ 468 } 469 470 joystick->naxes++; 471 } else { 472 /* not supported at this time */ 473 return DIENUM_CONTINUE; 474 } 475 476 joystick->hwdata->NumInputs++; 477 478 if (joystick->hwdata->NumInputs == MAX_INPUTS) { 479 return DIENUM_STOP; /* too many */ 480 } 481 482 return DIENUM_CONTINUE; 483} 484 485/* Sort using the data offset into the DInput struct. 486 * This gives a reasonable ordering for the inputs. 487 */ 488static int 489SortDevFunc(const void *a, const void *b) 490{ 491 const input_t *inputA = (const input_t*)a; 492 const input_t *inputB = (const input_t*)b; 493 494 if (inputA->ofs < inputB->ofs) 495 return -1; 496 if (inputA->ofs > inputB->ofs) 497 return 1; 498 return 0; 499} 500 501/* Sort the input objects and recalculate the indices for each input. */ 502static void 503SortDevObjects(SDL_Joystick *joystick) 504{ 505 input_t *inputs = joystick->hwdata->Inputs; 506 int nButtons = 0; 507 int nHats = 0; 508 int nAxis = 0; 509 int n; 510 511 SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc); 512 513 for (n = 0; n < joystick->hwdata->NumInputs; n++) { 514 switch (inputs[n].type) { 515 case BUTTON: 516 inputs[n].num = nButtons; 517 nButtons++; 518 break; 519 520 case HAT: 521 inputs[n].num = nHats; 522 nHats++; 523 break; 524 525 case AXIS: 526 inputs[n].num = nAxis; 527 nAxis++; 528 break; 529 } 530 } 531} 532 533int 534SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice) 535{ 536 HRESULT result; 537 LPDIRECTINPUTDEVICE8 device; 538 DIPROPDWORD dipdw; 539 540 joystick->hwdata->buffered = SDL_TRUE; 541 joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS); 542 543 SDL_zero(dipdw); 544 dipdw.diph.dwSize = sizeof(DIPROPDWORD); 545 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 546 547 result = 548 IDirectInput8_CreateDevice(dinput, 549 &(joystickdevice->dxdevice.guidInstance), &device, NULL); 550 if (FAILED(result)) { 551 return SetDIerror("IDirectInput::CreateDevice", result); 552 } 553 554 /* Now get the IDirectInputDevice8 interface, instead. */ 555 result = IDirectInputDevice8_QueryInterface(device, 556 &IID_IDirectInputDevice8, 557 (LPVOID *)& joystick-> 558 hwdata->InputDevice); 559 /* We are done with this object. Use the stored one from now on. */ 560 IDirectInputDevice8_Release(device); 561 562 if (FAILED(result)) { 563 return SetDIerror("IDirectInputDevice8::QueryInterface", result); 564 } 565 566 /* Acquire shared access. Exclusive access is required for forces, 567 * though. */ 568 result = 569 IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata-> 570 InputDevice, SDL_HelperWindow, 571 DISCL_EXCLUSIVE | 572 DISCL_BACKGROUND); 573 if (FAILED(result)) { 574 return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result); 575 } 576 577 /* Use the extended data structure: DIJOYSTATE2. */ 578 result = 579 IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice, 580 &c_dfDIJoystick2); 581 if (FAILED(result)) { 582 return SetDIerror("IDirectInputDevice8::SetDataFormat", result); 583 } 584 585 /* Get device capabilities */ 586 result = 587 IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice, 588 &joystick->hwdata->Capabilities); 589 if (FAILED(result)) { 590 return SetDIerror("IDirectInputDevice8::GetCapabilities", result); 591 } 592 593 /* Force capable? */ 594 if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) { 595 596 result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice); 597 if (FAILED(result)) { 598 return SetDIerror("IDirectInputDevice8::Acquire", result); 599 } 600 601 /* reset all actuators. */ 602 result = 603 IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata-> 604 InputDevice, 605 DISFFC_RESET); 606 607 /* Not necessarily supported, ignore if not supported. 608 if (FAILED(result)) { 609 return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result); 610 } 611 */ 612 613 result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice); 614 615 if (FAILED(result)) { 616 return SetDIerror("IDirectInputDevice8::Unacquire", result); 617 } 618 619 /* Turn on auto-centering for a ForceFeedback device (until told 620 * otherwise). */ 621 dipdw.diph.dwObj = 0; 622 dipdw.diph.dwHow = DIPH_DEVICE; 623 dipdw.dwData = DIPROPAUTOCENTER_ON; 624 625 result = 626 IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice, 627 DIPROP_AUTOCENTER, &dipdw.diph); 628 629 /* Not necessarily supported, ignore if not supported. 630 if (FAILED(result)) { 631 return SetDIerror("IDirectInputDevice8::SetProperty", result); 632 } 633 */ 634 } 635 636 /* What buttons and axes does it have? */ 637 IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice, 638 EnumDevObjectsCallback, joystick, 639 DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV); 640 641 /* Reorder the input objects. Some devices do not report the X axis as 642 * the first axis, for example. */ 643 SortDevObjects(joystick); 644 645 dipdw.diph.dwObj = 0; 646 dipdw.diph.dwHow = DIPH_DEVICE; 647 dipdw.dwData = INPUT_QSIZE; 648 649 /* Set the buffer size */ 650 result = 651 IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice, 652 DIPROP_BUFFERSIZE, &dipdw.diph); 653 654 if (result == DI_POLLEDDEVICE) { 655 /* This device doesn't support buffering, so we're forced 656 * to use less reliable polling. */ 657 joystick->hwdata->buffered = SDL_FALSE; 658 } else if (FAILED(result)) { 659 return SetDIerror("IDirectInputDevice8::SetProperty", result); 660 } 661 return 0; 662} 663 664static Uint8 665TranslatePOV(DWORD value) 666{ 667 const int HAT_VALS[] = { 668 SDL_HAT_UP, 669 SDL_HAT_UP | SDL_HAT_RIGHT, 670 SDL_HAT_RIGHT, 671 SDL_HAT_DOWN | SDL_HAT_RIGHT, 672 SDL_HAT_DOWN, 673 SDL_HAT_DOWN | SDL_HAT_LEFT, 674 SDL_HAT_LEFT, 675 SDL_HAT_UP | SDL_HAT_LEFT 676 }; 677 678 if (LOWORD(value) == 0xFFFF) 679 return SDL_HAT_CENTERED; 680 681 /* Round the value up: */ 682 value += 4500 / 2; 683 value %= 36000; 684 value /= 4500; 685 686 if (value >= 8) 687 return SDL_HAT_CENTERED; /* shouldn't happen */ 688 689 return HAT_VALS[value]; 690} 691 692static void 693UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick) 694{ 695 int i; 696 HRESULT result; 697 DWORD numevents; 698 DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; 699 700 numevents = INPUT_QSIZE; 701 result = 702 IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice, 703 sizeof(DIDEVICEOBJECTDATA), evtbuf, 704 &numevents, 0); 705 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { 706 IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice); 707 result = 708 IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice, 709 sizeof(DIDEVICEOBJECTDATA), 710 evtbuf, &numevents, 0); 711 } 712 713 /* Handle the events or punt */ 714 if (FAILED(result)) { 715 joystick->hwdata->send_remove_event = SDL_TRUE; 716 joystick->hwdata->removed = SDL_TRUE; 717 return; 718 } 719 720 for (i = 0; i < (int)numevents; ++i) { 721 int j; 722 723 for (j = 0; j < joystick->hwdata->NumInputs; ++j) { 724 const input_t *in = &joystick->hwdata->Inputs[j]; 725 726 if (evtbuf[i].dwOfs != in->ofs) 727 continue; 728 729 switch (in->type) { 730 case AXIS: 731 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData); 732 break; 733 case BUTTON: 734 SDL_PrivateJoystickButton(joystick, in->num, 735 (Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED)); 736 break; 737 case HAT: 738 { 739 Uint8 pos = TranslatePOV(evtbuf[i].dwData); 740 SDL_PrivateJoystickHat(joystick, in->num, pos); 741 } 742 break; 743 } 744 } 745 } 746} 747 748/* Function to update the state of a joystick - called as a device poll. 749 * This function shouldn't update the joystick structure directly, 750 * but instead should call SDL_PrivateJoystick*() to deliver events 751 * and update joystick device state. 752 */ 753static void 754UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick) 755{ 756 DIJOYSTATE2 state; 757 HRESULT result; 758 int i; 759 760 result = 761 IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice, 762 sizeof(DIJOYSTATE2), &state); 763 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { 764 IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice); 765 result = 766 IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice, 767 sizeof(DIJOYSTATE2), &state); 768 } 769 770 if (result != DI_OK) { 771 joystick->hwdata->send_remove_event = SDL_TRUE; 772 joystick->hwdata->removed = SDL_TRUE; 773 return; 774 } 775 776 /* Set each known axis, button and POV. */ 777 for (i = 0; i < joystick->hwdata->NumInputs; ++i) { 778 const input_t *in = &joystick->hwdata->Inputs[i]; 779 780 switch (in->type) { 781 case AXIS: 782 switch (in->ofs) { 783 case DIJOFS_X: 784 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX); 785 break; 786 case DIJOFS_Y: 787 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY); 788 break; 789 case DIJOFS_Z: 790 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ); 791 break; 792 case DIJOFS_RX: 793 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx); 794 break; 795 case DIJOFS_RY: 796 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy); 797 break; 798 case DIJOFS_RZ: 799 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz); 800 break; 801 case DIJOFS_SLIDER(0): 802 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]); 803 break; 804 case DIJOFS_SLIDER(1): 805 SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]); 806 break; 807 } 808 break; 809 810 case BUTTON: 811 SDL_PrivateJoystickButton(joystick, in->num, 812 (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED)); 813 break; 814 case HAT: 815 { 816 Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]); 817 SDL_PrivateJoystickHat(joystick, in->num, pos); 818 break; 819 } 820 } 821 } 822} 823 824void 825SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick) 826{ 827 HRESULT result; 828 829 result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice); 830 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { 831 IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice); 832 IDirectInputDevice8_Poll(joystick->hwdata->InputDevice); 833 } 834 835 if (joystick->hwdata->buffered) { 836 UpdateDINPUTJoystickState_Buffered(joystick); 837 } else { 838 UpdateDINPUTJoystickState_Polled(joystick); 839 } 840} 841 842void 843SDL_DINPUT_JoystickClose(SDL_Joystick * joystick) 844{ 845 IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice); 846 IDirectInputDevice8_Release(joystick->hwdata->InputDevice); 847} 848 849void 850SDL_DINPUT_JoystickQuit(void) 851{ 852 if (dinput != NULL) { 853 IDirectInput8_Release(dinput); 854 dinput = NULL; 855 } 856 857 if (coinitialized) { 858 WIN_CoUninitialize(); 859 coinitialized = SDL_FALSE; 860 } 861} 862 863#else /* !SDL_JOYSTICK_DINPUT */ 864 865 866int 867SDL_DINPUT_JoystickInit(void) 868{ 869 return 0; 870} 871 872void 873SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext) 874{ 875} 876 877int 878SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice) 879{ 880 return SDL_Unsupported(); 881} 882 883void 884SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick) 885{ 886} 887 888void 889SDL_DINPUT_JoystickClose(SDL_Joystick * joystick) 890{ 891} 892 893void 894SDL_DINPUT_JoystickQuit(void) 895{ 896} 897 898#endif /* SDL_JOYSTICK_DINPUT */ 899 900/* vi: set ts=4 sw=4 expandtab: */