comparison src/joystick/win32/SDL_dxjoystick.c @ 2198:fe19afb86473

Split acinclude.m4 into its component parts for easy updating
author Sam Lantinga <slouken@libsdl.org>
date Sun, 15 Jul 2007 01:51:11 +0000
parents c121d94672cb
children 034440120c38 e1da92da346c 0906692aa6a4
comparison
equal deleted inserted replaced
2197:2ff40f30af31 2198:fe19afb86473
42 #define WIN32_LEAN_AND_MEAN 42 #define WIN32_LEAN_AND_MEAN
43 #include <windows.h> 43 #include <windows.h>
44 44
45 #define DIRECTINPUT_VERSION 0x0500 45 #define DIRECTINPUT_VERSION 0x0500
46 #include <dinput.h> 46 #include <dinput.h>
47 #ifdef _MSC_VER
48 /* Used for the c_dfDIJoystick2 symbol (no imports are used) */
49 # pragma comment (lib, "dinput.lib")
50 #endif
51 #include <dxerr9.h> /* From DirectX SDK 9c */
52 #ifdef _MSC_VER
53 # pragma comment (lib, "dxerr9.lib")
54 #endif
55
56 /* an ISO hack for VisualC++ */
57 #ifdef _MSC_VER
58 #define snprintf _snprintf
59 #endif
47 60
48 #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */ 61 #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
49
50 extern HINSTANCE SDL_Instance;
51 extern int DX5_Load();
52 extern void DX5_Unload();
53 extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
54 LPDIRECTINPUT * ppDI,
55 LPUNKNOWN punkOuter);
56
57 static LPDIRECTINPUT dinput = NULL;
58
59 #define MAX_JOYSTICKS 8 62 #define MAX_JOYSTICKS 8
60 #define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */ 63 #define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */
61 #define AXIS_MIN -32768 /* minimum value for axis coordinate */ 64 #define AXIS_MIN -32768 /* minimum value for axis coordinate */
62 #define AXIS_MAX 32767 /* maximum value for axis coordinate */ 65 #define AXIS_MAX 32767 /* maximum value for axis coordinate */
63 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */ 66 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
64 67
68 /* external variables referenced. */
69 extern HINSTANCE SDL_Instance;
70 extern HWND SDL_Window;
71
72
73 /* local variables */
74 static LPDIRECTINPUT dinput = NULL;
75 extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
76 LPDIRECTINPUT * ppDI,
77 LPUNKNOWN punkOuter);
78 static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS]; /* array to hold joystick ID values */
79 static int SYS_NumJoysticks;
80 static HINSTANCE DInputDLL = NULL;
81
82
83 /* local prototypes */
84 static void SetDIerror(const char *function, HRESULT code);
85 static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE *
86 pdidInstance, VOID * pContext);
87 static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev,
88 LPVOID pvRef);
89 static Uint8 TranslatePOV(DWORD value);
90 static int SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis,
91 Sint16 value);
92 static int SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat,
93 Uint8 value);
94 static int SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick,
95 Uint8 button, Uint8 state);
96
97
98 /* local types */
65 typedef enum Type 99 typedef enum Type
66 { BUTTON, AXIS, HAT } Type; 100 { BUTTON, AXIS, HAT } Type;
67
68 /* array to hold joystick ID values */
69 static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS];
70 static int SYS_NumJoysticks;
71
72 extern HWND SDL_Window;
73 101
74 typedef struct input_t 102 typedef struct input_t
75 { 103 {
76 /* DirectInput offset for this input type: */ 104 /* DirectInput offset for this input type: */
77 DWORD ofs; 105 DWORD ofs;
85 113
86 /* The private structure used to keep track of a joystick */ 114 /* The private structure used to keep track of a joystick */
87 struct joystick_hwdata 115 struct joystick_hwdata
88 { 116 {
89 LPDIRECTINPUTDEVICE2 InputDevice; 117 LPDIRECTINPUTDEVICE2 InputDevice;
118 DIDEVCAPS Capabilities;
90 int buffered; 119 int buffered;
91 120
92 input_t Inputs[MAX_INPUTS]; 121 input_t Inputs[MAX_INPUTS];
93 int NumInputs; 122 int NumInputs;
94 }; 123 };
95 124
96 /* Convert a DirectInput return code to a text message */ 125 /* Convert a DirectInput return code to a text message */
97 static void 126 static void
98 SetDIerror(char *function, int code) 127 SetDIerror(const char *function, HRESULT code)
99 { 128 {
100 static char *error; 129 SDL_SetError("%s() [%s]: %s", function,
101 static char errbuf[1024]; 130 DXGetErrorString9(code), DXGetErrorDescription9(code));
102 131 }
103 errbuf[0] = 0; 132
104 switch (code) { 133
105 case DIERR_GENERIC: 134 /* Function to scan the system for joysticks.
106 error = "Undefined error!"; 135 * This function should set SDL_numjoysticks to the number of available
107 break; 136 * joysticks. Joystick 0 should be the system default joystick.
108 case DIERR_OLDDIRECTINPUTVERSION: 137 * It should return 0, or -1 on an unrecoverable fatal error.
109 error = "Your version of DirectInput needs upgrading"; 138 */
110 break; 139 int
111 case DIERR_INVALIDPARAM: 140 SDL_SYS_JoystickInit(void)
112 error = "Invalid parameters"; 141 {
113 break; 142 HRESULT result;
114 case DIERR_OUTOFMEMORY: 143
115 error = "Out of memory"; 144 SYS_NumJoysticks = 0;
116 break; 145
117 case DIERR_DEVICENOTREG: 146 result = CoInitialize(NULL);
118 error = "Device not registered"; 147 if (FAILED(result)) {
119 break; 148 SetDIerror("CoInitialize", result);
120 case DIERR_NOINTERFACE: 149 return (-1);
121 error = "Interface not supported"; 150 }
122 break; 151
123 case DIERR_NOTINITIALIZED: 152 result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
124 error = "Device not initialized"; 153 &IID_IDirectInput, &dinput);
125 break; 154
126 default: 155 if (FAILED(result)) {
127 sprintf(errbuf, "%s: Unknown DirectInput error: 0x%x", 156 SetDIerror("CoCreateInstance", result);
128 function, code); 157 return (-1);
129 break; 158 }
130 } 159
131 if (!errbuf[0]) { 160 /* Because we used CoCreateInstance, we need to Initialize it, first. */
132 sprintf(errbuf, "%s: %s", function, error); 161 result =
133 } 162 IDirectInput_Initialize(dinput, SDL_Instance, DIRECTINPUT_VERSION);
134 SDL_SetError("%s", errbuf); 163
135 return; 164 if (FAILED(result)) {
136 } 165 SetDIerror("IDirectInput::Initialize", result);
137 166 return (-1);
138 167 }
139 BOOL CALLBACK 168
169 /* Look for joysticks, wheels, head trackers, gamepads, etc.. */
170 result = IDirectInput_EnumDevices(dinput,
171 DIDEVTYPE_JOYSTICK,
172 EnumJoysticksCallback,
173 NULL, DIEDFL_ATTACHEDONLY);
174
175 return SYS_NumJoysticks;
176 }
177
178 static BOOL CALLBACK
140 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) 179 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
141 { 180 {
142 memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance, 181 memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance,
143 sizeof(DIDEVICEINSTANCE)); 182 sizeof(DIDEVICEINSTANCE));
144 SYS_NumJoysticks++; 183 SYS_NumJoysticks++;
147 return DIENUM_STOP; 186 return DIENUM_STOP;
148 187
149 return DIENUM_CONTINUE; 188 return DIENUM_CONTINUE;
150 } 189 }
151 190
191 /* Function to get the device-dependent name of a joystick */
192 const char *
193 SDL_SYS_JoystickName(int index)
194 {
195 /***-> test for invalid index ? */
196 return (SYS_Joystick[index].tszProductName);
197 }
198
199 /* Function to open a joystick for use.
200 The joystick to open is specified by the index field of the joystick.
201 This should fill the nbuttons and naxes fields of the joystick structure.
202 It returns 0, or -1 if there is an error.
203 */
204 int
205 SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
206 {
207 HRESULT result;
208 LPDIRECTINPUTDEVICE device;
209 DIPROPDWORD dipdw;
210
211 ZeroMemory(&dipdw, sizeof(DIPROPDWORD));
212 dipdw.diph.dwSize = sizeof(DIPROPDWORD);
213 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
214
215
216 /* allocate memory for system specific hardware data */
217 joystick->hwdata =
218 (struct joystick_hwdata *) malloc(sizeof(struct joystick_hwdata));
219 if (joystick->hwdata == NULL) {
220 SDL_OutOfMemory();
221 return (-1);
222 }
223 ZeroMemory(joystick->hwdata, sizeof(struct joystick_hwdata));
224 joystick->hwdata->buffered = 1;
225 joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
226
227 result =
228 IDirectInput_CreateDevice(dinput,
229 &SYS_Joystick[joystick->index].
230 guidInstance, &device, NULL);
231 if (FAILED(result)) {
232 SetDIerror("IDirectInput::CreateDevice", result);
233 return (-1);
234 }
235
236 /* Now get the IDirectInputDevice2 interface, instead. */
237 result = IDirectInputDevice_QueryInterface(device,
238 &IID_IDirectInputDevice2,
239 (LPVOID *) & joystick->
240 hwdata->InputDevice);
241 /* We are done with this object. Use the stored one from now on. */
242 IDirectInputDevice_Release(device);
243
244 if (FAILED(result)) {
245 SetDIerror("IDirectInputDevice::QueryInterface", result);
246 return (-1);
247 }
248
249 /* Aquire shared access. Exclusive access is required for forces,
250 * though. */
251 result =
252 IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->
253 InputDevice, SDL_Window,
254 DISCL_EXCLUSIVE |
255 DISCL_BACKGROUND);
256 if (FAILED(result)) {
257 SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result);
258 return (-1);
259 }
260
261 /* Use the extended data structure: DIJOYSTATE2. */
262 result =
263 IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice,
264 &c_dfDIJoystick2);
265 if (FAILED(result)) {
266 SetDIerror("IDirectInputDevice2::SetDataFormat", result);
267 return (-1);
268 }
269
270 /* Get device capabilities */
271 result =
272 IDirectInputDevice2_GetCapabilities(joystick->hwdata->InputDevice,
273 &joystick->hwdata->Capabilities);
274
275 if (FAILED(result)) {
276 SetDIerror("IDirectInputDevice2::GetCapabilities", result);
277 return (-1);
278 }
279
280 /* Force capable? */
281 if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
282
283 result = IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
284
285 if (FAILED(result)) {
286 SetDIerror("IDirectInputDevice2::Acquire", result);
287 return (-1);
288 }
289
290 /* reset all accuators. */
291 result =
292 IDirectInputDevice2_SendForceFeedbackCommand(joystick->hwdata->
293 InputDevice,
294 DISFFC_RESET);
295
296 if (FAILED(result)) {
297 SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand",
298 result);
299 return (-1);
300 }
301
302 result = IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
303
304 if (FAILED(result)) {
305 SetDIerror("IDirectInputDevice2::Unacquire", result);
306 return (-1);
307 }
308
309 /* Turn on auto-centering for a ForceFeedback device (until told
310 * otherwise). */
311 dipdw.diph.dwObj = 0;
312 dipdw.diph.dwHow = DIPH_DEVICE;
313 dipdw.dwData = DIPROPAUTOCENTER_ON;
314
315 result =
316 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
317 DIPROP_AUTOCENTER, &dipdw.diph);
318
319 if (FAILED(result)) {
320 SetDIerror("IDirectInputDevice2::SetProperty", result);
321 return (-1);
322 }
323 }
324
325 /* What buttons and axes does it have? */
326 IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice,
327 EnumDevObjectsCallback, joystick,
328 DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
329
330 dipdw.diph.dwObj = 0;
331 dipdw.diph.dwHow = DIPH_DEVICE;
332 dipdw.dwData = INPUT_QSIZE;
333
334 /* Set the buffer size */
335 result =
336 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
337 DIPROP_BUFFERSIZE, &dipdw.diph);
338
339 if (result == DI_POLLEDDEVICE) {
340 /* This device doesn't support buffering, so we're forced
341 * to use less reliable polling. */
342 joystick->hwdata->buffered = 0;
343 } else if (FAILED(result)) {
344 SetDIerror("IDirectInputDevice2::SetProperty", result);
345 return (-1);
346 }
347
348 return (0);
349 }
350
152 static BOOL CALLBACK 351 static BOOL CALLBACK
153 DIJoystick_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) 352 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
154 { 353 {
155 SDL_Joystick *joystick = (SDL_Joystick *) pvRef; 354 SDL_Joystick *joystick = (SDL_Joystick *) pvRef;
156 HRESULT result; 355 HRESULT result;
157 input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; 356 input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
158 const int SupportedMask = DIDFT_BUTTON | DIDFT_POV | DIDFT_AXIS;
159 if (!(dev->dwType & SupportedMask))
160 return DIENUM_CONTINUE; /* unsupported */
161 357
162 in->ofs = dev->dwOfs; 358 in->ofs = dev->dwOfs;
163 359
164 if (dev->dwType & DIDFT_BUTTON) { 360 if (dev->dwType & DIDFT_BUTTON) {
165 in->type = BUTTON; 361 in->type = BUTTON;
167 joystick->nbuttons++; 363 joystick->nbuttons++;
168 } else if (dev->dwType & DIDFT_POV) { 364 } else if (dev->dwType & DIDFT_POV) {
169 in->type = HAT; 365 in->type = HAT;
170 in->num = joystick->nhats; 366 in->num = joystick->nhats;
171 joystick->nhats++; 367 joystick->nhats++;
172 } else { /* dev->dwType & DIDFT_AXIS */ 368 } else if (dev->dwType & DIDFT_AXIS) {
173 DIPROPRANGE diprg; 369 DIPROPRANGE diprg;
174 DIPROPDWORD dilong; 370 DIPROPDWORD dilong;
175 371
176 in->type = AXIS; 372 in->type = AXIS;
177 in->num = joystick->naxes; 373 in->num = joystick->naxes;
184 diprg.lMax = AXIS_MAX; 380 diprg.lMax = AXIS_MAX;
185 381
186 result = 382 result =
187 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, 383 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
188 DIPROP_RANGE, &diprg.diph); 384 DIPROP_RANGE, &diprg.diph);
189 if (result != DI_OK) 385 if (FAILED(result)) {
190 return DIENUM_CONTINUE; /* don't use this axis */ 386 return DIENUM_CONTINUE; /* don't use this axis */
387 }
191 388
192 /* Set dead zone to 0. */ 389 /* Set dead zone to 0. */
193 dilong.diph.dwSize = sizeof(dilong); 390 dilong.diph.dwSize = sizeof(dilong);
194 dilong.diph.dwHeaderSize = sizeof(dilong.diph); 391 dilong.diph.dwHeaderSize = sizeof(dilong.diph);
195 dilong.diph.dwObj = dev->dwOfs; 392 dilong.diph.dwObj = dev->dwOfs;
196 dilong.diph.dwHow = DIPH_BYOFFSET; 393 dilong.diph.dwHow = DIPH_BYOFFSET;
197 dilong.dwData = 0; 394 dilong.dwData = 0;
198 result = 395 result =
199 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, 396 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
200 DIPROP_DEADZONE, &dilong.diph); 397 DIPROP_DEADZONE, &dilong.diph);
201 if (result != DI_OK) 398 if (FAILED(result)) {
202 return DIENUM_CONTINUE; /* don't use this axis */ 399 return DIENUM_CONTINUE; /* don't use this axis */
400 }
203 401
204 joystick->naxes++; 402 joystick->naxes++;
403 } else {
404 /* not supported at this time */
405 return DIENUM_CONTINUE;
205 } 406 }
206 407
207 joystick->hwdata->NumInputs++; 408 joystick->hwdata->NumInputs++;
208 409
209 if (joystick->hwdata->NumInputs == MAX_INPUTS) 410 if (joystick->hwdata->NumInputs == MAX_INPUTS) {
210 return DIENUM_STOP; /* too many */ 411 return DIENUM_STOP; /* too many */
412 }
211 413
212 return DIENUM_CONTINUE; 414 return DIENUM_CONTINUE;
213 } 415 }
214 416
215 /* Function to scan the system for joysticks. 417 /* Function to update the state of a joystick - called as a device poll.
216 * This function should set SDL_numjoysticks to the number of available 418 * This function shouldn't update the joystick structure directly,
217 * joysticks. Joystick 0 should be the system default joystick. 419 * but instead should call SDL_PrivateJoystick*() to deliver events
218 * It should return 0, or -1 on an unrecoverable fatal error. 420 * and update joystick device state.
219 */ 421 */
220 int 422 void
221 SDL_SYS_JoystickInit(void) 423 SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick)
222 { 424 {
425 DIJOYSTATE2 state;
223 HRESULT result; 426 HRESULT result;
224 427 int i;
225 SYS_NumJoysticks = 0; 428
226 429 result =
227 /* Create the DirectInput object */ 430 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
228 if (DX5_Load() < 0) { 431 sizeof(DIJOYSTATE2), &state);
229 SDL_SetError("Couldn't load DirectInput"); 432 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
230 return (-1); 433 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
231 } 434 result =
232 result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, &dinput, NULL); 435 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
233 if (result != DI_OK) { 436 sizeof(DIJOYSTATE2), &state);
234 DX5_Unload(); 437 }
235 SetDIerror("DirectInputCreate", result); 438
236 return (-1); 439 /* Set each known axis, button and POV. */
237 } 440 for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
238 441 const input_t *in = &joystick->hwdata->Inputs[i];
239 result = IDirectInput_EnumDevices(dinput, 442
240 DIDEVTYPE_JOYSTICK, 443 switch (in->type) {
241 EnumJoysticksCallback, 444 case AXIS:
242 NULL, DIEDFL_ATTACHEDONLY); 445 switch (in->ofs) {
243 446 case DIJOFS_X:
244 return SYS_NumJoysticks; 447 SDL_PrivateJoystickAxis_Int(joystick, in->num,
245 } 448 (Sint16) state.lX);
246 449 break;
247 /* Function to get the device-dependent name of a joystick */ 450 case DIJOFS_Y:
248 const char * 451 SDL_PrivateJoystickAxis_Int(joystick, in->num,
249 SDL_SYS_JoystickName(int index) 452 (Sint16) state.lY);
250 { 453 break;
251 /***-> test for invalid index ? */ 454 case DIJOFS_Z:
252 return (SYS_Joystick[index].tszProductName); 455 SDL_PrivateJoystickAxis_Int(joystick, in->num,
253 } 456 (Sint16) state.lZ);
254 457 break;
255 /* Function to open a joystick for use. 458 case DIJOFS_RX:
256 The joystick to open is specified by the index field of the joystick. 459 SDL_PrivateJoystickAxis_Int(joystick, in->num,
257 This should fill the nbuttons and naxes fields of the joystick structure. 460 (Sint16) state.lRx);
258 It returns 0, or -1 if there is an error. 461 break;
259 */ 462 case DIJOFS_RY:
260 int 463 SDL_PrivateJoystickAxis_Int(joystick, in->num,
261 SDL_SYS_JoystickOpen(SDL_Joystick * joystick) 464 (Sint16) state.lRy);
262 { 465 break;
466 case DIJOFS_RZ:
467 SDL_PrivateJoystickAxis_Int(joystick, in->num,
468 (Sint16) state.lRz);
469 break;
470 case DIJOFS_SLIDER(0):
471 SDL_PrivateJoystickAxis_Int(joystick, in->num,
472 (Sint16) state.rglSlider[0]);
473 break;
474 case DIJOFS_SLIDER(1):
475 SDL_PrivateJoystickAxis_Int(joystick, in->num,
476 (Sint16) state.rglSlider[1]);
477 break;
478 }
479
480 break;
481
482 case BUTTON:
483 SDL_PrivateJoystickButton_Int(joystick, in->num,
484 (Uint8) (state.
485 rgbButtons[in->ofs -
486 DIJOFS_BUTTON0]
487 ? SDL_PRESSED :
488 SDL_RELEASED));
489 break;
490 case HAT:
491 {
492 Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs -
493 DIJOFS_POV(0)]);
494 SDL_PrivateJoystickHat_Int(joystick, in->num, pos);
495 break;
496 }
497 }
498 }
499 }
500
501 void
502 SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
503 {
504 int i;
263 HRESULT result; 505 HRESULT result;
264 LPDIRECTINPUTDEVICE device; 506 DWORD numevents;
265 507 DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
266 /* allocate memory for system specific hardware data */ 508
267 joystick->hwdata = 509 numevents = INPUT_QSIZE;
268 (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata)); 510 result =
269 if (joystick->hwdata == NULL) { 511 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
270 SDL_OutOfMemory(); 512 sizeof(DIDEVICEOBJECTDATA), evtbuf,
271 return (-1); 513 &numevents, 0);
272 } 514 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
273 memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); 515 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
274 joystick->hwdata->buffered = 1;
275
276 result =
277 IDirectInput_CreateDevice(dinput,
278 &SYS_Joystick[joystick->index].
279 guidInstance, &device, NULL);
280 if (result != DI_OK) {
281 SetDIerror("DirectInput::CreateDevice", result);
282 return (-1);
283 }
284
285 result = IDirectInputDevice_QueryInterface(device,
286 &IID_IDirectInputDevice2,
287 (LPVOID *) & joystick->
288 hwdata->InputDevice);
289 IDirectInputDevice_Release(device);
290 if (result != DI_OK) {
291 SetDIerror("DirectInputDevice::QueryInterface", result);
292 return (-1);
293 }
294
295 result =
296 IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->
297 InputDevice, SDL_Window,
298 DISCL_NONEXCLUSIVE |
299 DISCL_BACKGROUND);
300 if (result != DI_OK) {
301 SetDIerror("DirectInputDevice::SetCooperativeLevel", result);
302 return (-1);
303 }
304
305 result =
306 IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice,
307 &c_dfDIJoystick);
308 if (result != DI_OK) {
309 SetDIerror("DirectInputDevice::SetDataFormat", result);
310 return (-1);
311 }
312
313 IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice,
314 DIJoystick_EnumDevObjectsProc,
315 joystick,
316 DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
317
318 {
319 DIPROPDWORD dipdw;
320 memset(&dipdw, 0, sizeof(dipdw));
321 dipdw.diph.dwSize = sizeof(dipdw);
322 dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
323 dipdw.diph.dwObj = 0;
324 dipdw.diph.dwHow = DIPH_DEVICE;
325 dipdw.dwData = INPUT_QSIZE;
326 result = 516 result =
327 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, 517 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
328 DIPROP_BUFFERSIZE, &dipdw.diph); 518 sizeof(DIDEVICEOBJECTDATA),
329 519 evtbuf, &numevents, 0);
330 if (result == DI_POLLEDDEVICE) { 520 }
331 /* This device doesn't support buffering, so we're forced 521
332 * to use less reliable polling. */ 522 /* Handle the events or punt */
333 joystick->hwdata->buffered = 0; 523 if (FAILED(result))
334 } else if (result != DI_OK) { 524 return;
335 SetDIerror("DirectInputDevice::SetProperty", result); 525
336 return (-1); 526 for (i = 0; i < (int) numevents; ++i) {
337 } 527 int j;
338 } 528
339 529 for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
340 return (0); 530 const input_t *in = &joystick->hwdata->Inputs[j];
341 } 531
532 if (evtbuf[i].dwOfs != in->ofs)
533 continue;
534
535 switch (in->type) {
536 case AXIS:
537 SDL_PrivateJoystickAxis(joystick, in->num,
538 (Sint16) evtbuf[i].dwData);
539 break;
540 case BUTTON:
541 SDL_PrivateJoystickButton(joystick, in->num,
542 (Uint8) (evtbuf[i].
543 dwData ? SDL_PRESSED :
544 SDL_RELEASED));
545 break;
546 case HAT:
547 {
548 Uint8 pos = TranslatePOV(evtbuf[i].dwData);
549 SDL_PrivateJoystickHat(joystick, in->num, pos);
550 }
551 }
552 }
553 }
554 }
555
342 556
343 static Uint8 557 static Uint8
344 TranslatePOV(DWORD value) 558 TranslatePOV(DWORD value)
345 { 559 {
346 const int HAT_VALS[] = { 560 const int HAT_VALS[] = {
393 if (joystick->buttons[button] != state) 607 if (joystick->buttons[button] != state)
394 return SDL_PrivateJoystickButton(joystick, button, state); 608 return SDL_PrivateJoystickButton(joystick, button, state);
395 return 0; 609 return 0;
396 } 610 }
397 611
398 /* Function to update the state of a joystick - called as a device poll.
399 * This function shouldn't update the joystick structure directly,
400 * but instead should call SDL_PrivateJoystick*() to deliver events
401 * and update joystick device state.
402 */
403 void
404 SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick)
405 {
406 DIJOYSTATE state;
407 HRESULT result;
408 int i;
409
410 result =
411 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
412 sizeof(state), &state);
413 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
414 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
415 result =
416 IDirectInputDevice2_GetDeviceState(joystick->hwdata->
417 InputDevice, sizeof(state),
418 &state);
419 }
420
421 /* Set each known axis, button and POV. */
422 for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
423 const input_t *in = &joystick->hwdata->Inputs[i];
424
425 switch (in->type) {
426 case AXIS:
427 switch (in->ofs) {
428 case DIJOFS_X:
429 SDL_PrivateJoystickAxis_Int(joystick, in->num,
430 (Sint16) state.lX);
431 break;
432 case DIJOFS_Y:
433 SDL_PrivateJoystickAxis_Int(joystick, in->num,
434 (Sint16) state.lY);
435 break;
436 case DIJOFS_Z:
437 SDL_PrivateJoystickAxis_Int(joystick, in->num,
438 (Sint16) state.lZ);
439 break;
440 case DIJOFS_RX:
441 SDL_PrivateJoystickAxis_Int(joystick, in->num,
442 (Sint16) state.lRx);
443 break;
444 case DIJOFS_RY:
445 SDL_PrivateJoystickAxis_Int(joystick, in->num,
446 (Sint16) state.lRy);
447 break;
448 case DIJOFS_RZ:
449 SDL_PrivateJoystickAxis_Int(joystick, in->num,
450 (Sint16) state.lRz);
451 break;
452 case DIJOFS_SLIDER(0):
453 SDL_PrivateJoystickAxis_Int(joystick, in->num,
454 (Sint16) state.rglSlider[0]);
455 break;
456 case DIJOFS_SLIDER(1):
457 SDL_PrivateJoystickAxis_Int(joystick, in->num,
458 (Sint16) state.rglSlider[0]);
459 break;
460 }
461
462 break;
463
464 case BUTTON:
465 SDL_PrivateJoystickButton_Int(joystick, in->num,
466 (Uint8) (state.
467 rgbButtons[in->ofs -
468 DIJOFS_BUTTON0]
469 ? SDL_PRESSED :
470 SDL_RELEASED));
471 break;
472 case HAT:
473 {
474 Uint8 pos =
475 TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
476 SDL_PrivateJoystickHat_Int(joystick, in->num, pos);
477 break;
478 }
479 }
480 }
481 }
482
483 void
484 SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
485 {
486 int i;
487 HRESULT result;
488 DWORD numevents;
489 DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
490
491 numevents = INPUT_QSIZE;
492 result =
493 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
494 sizeof(DIDEVICEOBJECTDATA),
495 evtbuf, &numevents, 0);
496 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
497 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
498 result =
499 IDirectInputDevice2_GetDeviceData(joystick->hwdata->
500 InputDevice,
501 sizeof(DIDEVICEOBJECTDATA),
502 evtbuf, &numevents, 0);
503 }
504
505 /* Handle the events */
506 if (result != DI_OK)
507 return;
508
509 for (i = 0; i < (int) numevents; ++i) {
510 int j;
511
512 for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
513 const input_t *in = &joystick->hwdata->Inputs[j];
514
515 if (evtbuf[i].dwOfs != in->ofs)
516 continue;
517
518 switch (in->type) {
519 case AXIS:
520 SDL_PrivateJoystickAxis(joystick, in->num,
521 (Sint16) evtbuf[i].dwData);
522 break;
523 case BUTTON:
524 SDL_PrivateJoystickButton(joystick, in->num,
525 (Uint8) (evtbuf[i].
526 dwData ? SDL_PRESSED
527 : SDL_RELEASED));
528 break;
529 case HAT:
530 {
531 Uint8 pos = TranslatePOV(evtbuf[i].dwData);
532 SDL_PrivateJoystickHat(joystick, in->num, pos);
533 }
534 }
535 }
536 }
537 }
538
539 void 612 void
540 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) 613 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
541 { 614 {
542 HRESULT result; 615 HRESULT result;
543 616
570 void 643 void
571 SDL_SYS_JoystickQuit(void) 644 SDL_SYS_JoystickQuit(void)
572 { 645 {
573 IDirectInput_Release(dinput); 646 IDirectInput_Release(dinput);
574 dinput = NULL; 647 dinput = NULL;
575 DX5_Unload();
576 } 648 }
577 649
578 #endif /* SDL_JOYSTICK_DINPUT */ 650 #endif /* SDL_JOYSTICK_DINPUT */
579 /* vi: set ts=4 sw=4 expandtab: */ 651 /* vi: set ts=4 sw=4 expandtab: */