2015-06-21 15:33:46 +00:00
|
|
|
/*
|
|
|
|
Simple DirectMedia Layer
|
2022-01-03 17:40:00 +00:00
|
|
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*/
|
|
|
|
#include "../../SDL_internal.h"
|
|
|
|
|
|
|
|
#include "../SDL_sysjoystick.h"
|
|
|
|
|
|
|
|
#if SDL_JOYSTICK_DINPUT
|
|
|
|
|
|
|
|
#include "SDL_windowsjoystick_c.h"
|
|
|
|
#include "SDL_dinputjoystick_c.h"
|
2020-03-16 19:23:38 +00:00
|
|
|
#include "SDL_rawinputjoystick_c.h"
|
2015-06-21 15:33:46 +00:00
|
|
|
#include "SDL_xinputjoystick_c.h"
|
2018-08-09 23:00:17 +00:00
|
|
|
#include "../hidapi/SDL_hidapijoystick_c.h"
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
#ifndef DIDFT_OPTIONAL
|
|
|
|
#define DIDFT_OPTIONAL 0x80000000
|
|
|
|
#endif
|
|
|
|
|
2021-07-24 22:58:33 +00:00
|
|
|
#define INPUT_QSIZE 128 /* Buffer up to 128 input messages */
|
2016-12-27 09:39:07 +00:00
|
|
|
#define JOY_AXIS_THRESHOLD (((SDL_JOYSTICK_AXIS_MAX)-(SDL_JOYSTICK_AXIS_MIN))/100) /* 1% motion */
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
#define CONVERT_MAGNITUDE(x) (((x)*10000) / 0x7FFF)
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
/* external variables referenced. */
|
|
|
|
extern HWND SDL_HelperWindow;
|
|
|
|
|
|
|
|
/* local variables */
|
|
|
|
static SDL_bool coinitialized = SDL_FALSE;
|
|
|
|
static LPDIRECTINPUT8 dinput = NULL;
|
|
|
|
|
|
|
|
/* Taken from Wine - Thanks! */
|
|
|
|
static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
|
2021-01-22 17:20:02 +00:00
|
|
|
{ &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
|
|
|
{ &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
|
|
|
{ &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
|
|
|
{ &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
|
|
|
{ &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
|
|
|
{ &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
|
2018-08-09 23:00:17 +00:00
|
|
|
{ &GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ &GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ &GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ &GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(0), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(1), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(2), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(3), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(4), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(5), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(6), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(7), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(8), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(9), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(10), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(11), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(12), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(13), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(14), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(15), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(16), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(17), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(18), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(19), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(20), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(21), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(22), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(23), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(24), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(25), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(26), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(27), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(28), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(29), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(30), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(31), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(32), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(33), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(34), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(35), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(36), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(37), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(38), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(39), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(40), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(41), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(42), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(43), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(44), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(45), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(46), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(47), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(48), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(49), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(50), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(51), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(52), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(53), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(54), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(55), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(56), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(57), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(58), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(59), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(60), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(61), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(62), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(63), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(64), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(65), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(66), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(67), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(68), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(69), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(70), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(71), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(72), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(73), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(74), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(75), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(76), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(77), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(78), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(79), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(80), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(81), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(82), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(83), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(84), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(85), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(86), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(87), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(88), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(89), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(90), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(91), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(92), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(93), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(94), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(95), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(96), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(97), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(98), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(99), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(100), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(101), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(102), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(103), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(104), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(105), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(106), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(107), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(108), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(109), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(110), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(111), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(112), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(113), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(114), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(115), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(116), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(117), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(118), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(119), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(120), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(121), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(122), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(123), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(124), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(125), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(126), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
|
|
|
{ NULL, DIJOFS_BUTTON(127), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
2021-01-22 17:20:02 +00:00
|
|
|
{ &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
{ &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
{ &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
{ &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
{ &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
{ &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
/* note: dwOfs value matches Windows */
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTVELOCITY },
|
|
|
|
{ &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
{ &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
{ &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
{ &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
{ &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
{ &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
/* note: dwOfs value matches Windows */
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTACCEL },
|
|
|
|
{ &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
|
|
|
{ &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
|
|
|
{ &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
|
|
|
{ &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
|
|
|
{ &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
|
|
|
{ &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
|
|
|
/* note: dwOfs value matches Windows */
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
|
|
|
{ &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, DIDOI_ASPECTFORCE },
|
2015-06-21 15:33:46 +00:00
|
|
|
};
|
|
|
|
|
2016-10-01 21:48:18 +00:00
|
|
|
const DIDATAFORMAT SDL_c_dfDIJoystick2 = {
|
2015-06-21 15:33:46 +00:00
|
|
|
sizeof(DIDATAFORMAT),
|
|
|
|
sizeof(DIOBJECTDATAFORMAT),
|
|
|
|
DIDF_ABSAXIS,
|
|
|
|
sizeof(DIJOYSTATE2),
|
|
|
|
SDL_arraysize(dfDIJoystick2),
|
|
|
|
dfDIJoystick2
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Convert a DirectInput return code to a text message */
|
|
|
|
static int
|
|
|
|
SetDIerror(const char *function, HRESULT code)
|
|
|
|
{
|
|
|
|
return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code);
|
|
|
|
}
|
|
|
|
|
2019-11-21 00:42:50 +00:00
|
|
|
static SDL_bool
|
2021-05-19 14:52:08 +00:00
|
|
|
SDL_IsXInputDevice(Uint16 vendor_id, Uint16 product_id, const char* hidPath)
|
2019-11-21 00:42:50 +00:00
|
|
|
{
|
2021-05-19 14:52:08 +00:00
|
|
|
SDL_GameControllerType type;
|
2019-11-22 21:12:12 +00:00
|
|
|
|
2021-11-07 22:00:47 +00:00
|
|
|
/* XInput and RawInput backends will pick up XInput-compatible devices */
|
|
|
|
if (!SDL_XINPUT_Enabled()
|
|
|
|
#ifdef SDL_JOYSTICK_RAWINPUT
|
|
|
|
&& !RAWINPUT_IsEnabled()
|
|
|
|
#endif
|
|
|
|
) {
|
2019-11-22 21:12:12 +00:00
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
2021-09-07 22:50:21 +00:00
|
|
|
/* If device path contains "IG_" then its an XInput device */
|
|
|
|
/* See: https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput */
|
|
|
|
if (SDL_strstr(hidPath, "IG_") != NULL) {
|
|
|
|
return SDL_TRUE;
|
|
|
|
}
|
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0);
|
|
|
|
if (type == SDL_CONTROLLER_TYPE_XBOX360 ||
|
|
|
|
type == SDL_CONTROLLER_TYPE_XBOXONE ||
|
2021-06-02 11:28:33 +00:00
|
|
|
(vendor_id == USB_VENDOR_VALVE && product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD)) {
|
2020-03-13 02:47:30 +00:00
|
|
|
return SDL_TRUE;
|
|
|
|
}
|
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
static SDL_bool
|
|
|
|
QueryDeviceName(LPDIRECTINPUTDEVICE8 device, char** device_name)
|
|
|
|
{
|
|
|
|
DIPROPSTRING dipstr;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
if (!device || !device_name) {
|
|
|
|
return SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
dipstr.diph.dwSize = sizeof(dipstr);
|
|
|
|
dipstr.diph.dwHeaderSize = sizeof(dipstr.diph);
|
|
|
|
dipstr.diph.dwObj = 0;
|
|
|
|
dipstr.diph.dwHow = DIPH_DEVICE;
|
|
|
|
|
|
|
|
if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_PRODUCTNAME, &dipstr.diph))) {
|
|
|
|
return SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
*device_name = WIN_StringToUTF8(dipstr.wsz);
|
|
|
|
|
|
|
|
return SDL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SDL_bool
|
|
|
|
QueryDevicePath(LPDIRECTINPUTDEVICE8 device, char** device_path)
|
|
|
|
{
|
|
|
|
DIPROPGUIDANDPATH dippath;
|
|
|
|
|
|
|
|
if (!device || !device_path) {
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dippath.diph.dwSize = sizeof(dippath);
|
|
|
|
dippath.diph.dwHeaderSize = sizeof(dippath.diph);
|
|
|
|
dippath.diph.dwObj = 0;
|
|
|
|
dippath.diph.dwHow = DIPH_DEVICE;
|
|
|
|
|
|
|
|
if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_GUIDANDPATH, &dippath.diph))) {
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*device_path = WIN_StringToUTF8W(dippath.wszPath);
|
|
|
|
|
|
|
|
/* Normalize path to upper case. */
|
|
|
|
SDL_strupr(*device_path);
|
|
|
|
|
|
|
|
return SDL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SDL_bool
|
|
|
|
QueryDeviceInfo(LPDIRECTINPUTDEVICE8 device, Uint16* vendor_id, Uint16* product_id)
|
|
|
|
{
|
|
|
|
DIPROPDWORD dipdw;
|
|
|
|
|
|
|
|
if (!device || !vendor_id || !product_id) {
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dipdw.diph.dwSize = sizeof(dipdw);
|
|
|
|
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
|
|
|
|
dipdw.diph.dwObj = 0;
|
|
|
|
dipdw.diph.dwHow = DIPH_DEVICE;
|
|
|
|
|
|
|
|
if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_VIDPID, &dipdw.diph))) {
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*vendor_id = LOWORD(dipdw.dwData);
|
|
|
|
*product_id = HIWORD(dipdw.dwData);
|
|
|
|
|
|
|
|
return SDL_TRUE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
void FreeRumbleEffectData(DIEFFECT *effect)
|
|
|
|
{
|
|
|
|
if (!effect) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SDL_free(effect->rgdwAxes);
|
|
|
|
SDL_free(effect->rglDirection);
|
|
|
|
SDL_free(effect->lpvTypeSpecificParams);
|
|
|
|
SDL_free(effect);
|
|
|
|
}
|
|
|
|
|
2020-02-04 20:48:53 +00:00
|
|
|
DIEFFECT *CreateRumbleEffectData(Sint16 magnitude)
|
2018-08-09 23:00:17 +00:00
|
|
|
{
|
|
|
|
DIEFFECT *effect;
|
|
|
|
DIPERIODIC *periodic;
|
|
|
|
|
|
|
|
/* Create the effect */
|
|
|
|
effect = (DIEFFECT *)SDL_calloc(1, sizeof(*effect));
|
|
|
|
if (!effect) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
effect->dwSize = sizeof(*effect);
|
|
|
|
effect->dwGain = 10000;
|
|
|
|
effect->dwFlags = DIEFF_OBJECTOFFSETS;
|
2020-02-04 20:48:53 +00:00
|
|
|
effect->dwDuration = SDL_MAX_RUMBLE_DURATION_MS * 1000; /* In microseconds. */
|
2018-08-09 23:00:17 +00:00
|
|
|
effect->dwTriggerButton = DIEB_NOTRIGGER;
|
|
|
|
|
|
|
|
effect->cAxes = 2;
|
|
|
|
effect->rgdwAxes = (DWORD *)SDL_calloc(effect->cAxes, sizeof(DWORD));
|
|
|
|
if (!effect->rgdwAxes) {
|
|
|
|
FreeRumbleEffectData(effect);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
effect->rglDirection = (LONG *)SDL_calloc(effect->cAxes, sizeof(LONG));
|
|
|
|
if (!effect->rglDirection) {
|
|
|
|
FreeRumbleEffectData(effect);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
effect->dwFlags |= DIEFF_CARTESIAN;
|
|
|
|
|
|
|
|
periodic = (DIPERIODIC *)SDL_calloc(1, sizeof(*periodic));
|
|
|
|
if (!periodic) {
|
|
|
|
FreeRumbleEffectData(effect);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
periodic->dwMagnitude = CONVERT_MAGNITUDE(magnitude);
|
|
|
|
periodic->dwPeriod = 1000000;
|
|
|
|
|
|
|
|
effect->cbTypeSpecificParams = sizeof(*periodic);
|
|
|
|
effect->lpvTypeSpecificParams = periodic;
|
|
|
|
|
|
|
|
return effect;
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
int
|
|
|
|
SDL_DINPUT_JoystickInit(void)
|
|
|
|
{
|
|
|
|
HRESULT result;
|
|
|
|
HINSTANCE instance;
|
|
|
|
|
|
|
|
result = WIN_CoInitialize();
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("CoInitialize", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
coinitialized = SDL_TRUE;
|
|
|
|
|
|
|
|
result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
|
2020-05-20 20:58:33 +00:00
|
|
|
&IID_IDirectInput8, (LPVOID *)&dinput);
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("CoCreateInstance", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Because we used CoCreateInstance, we need to Initialize it, first. */
|
|
|
|
instance = GetModuleHandle(NULL);
|
|
|
|
if (instance == NULL) {
|
2020-11-12 03:43:02 +00:00
|
|
|
IDirectInput8_Release(dinput);
|
|
|
|
dinput = NULL;
|
2015-06-21 15:33:46 +00:00
|
|
|
return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
|
|
|
|
}
|
|
|
|
result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
|
|
|
|
|
|
|
|
if (FAILED(result)) {
|
2020-11-12 03:43:02 +00:00
|
|
|
IDirectInput8_Release(dinput);
|
|
|
|
dinput = NULL;
|
2015-06-21 15:33:46 +00:00
|
|
|
return SetDIerror("IDirectInput::Initialize", result);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* helper function for direct input, gets called for each connected joystick */
|
|
|
|
static BOOL CALLBACK
|
2021-06-25 21:20:08 +00:00
|
|
|
EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2021-11-22 10:16:23 +00:00
|
|
|
#define CHECK(expression) { if(!(expression)) goto err; }
|
2021-05-19 14:52:08 +00:00
|
|
|
JoyStick_DeviceData *pNewJoystick = NULL;
|
2015-06-21 15:33:46 +00:00
|
|
|
JoyStick_DeviceData *pPrevJoystick = NULL;
|
2016-11-11 01:19:34 +00:00
|
|
|
Uint16 *guid16;
|
2018-08-09 23:00:17 +00:00
|
|
|
Uint16 vendor = 0;
|
|
|
|
Uint16 product = 0;
|
|
|
|
Uint16 version = 0;
|
2021-05-19 14:52:08 +00:00
|
|
|
char *hidPath = NULL;
|
|
|
|
char *name = NULL;
|
|
|
|
LPDIRECTINPUTDEVICE8 device = NULL;
|
Fixed bug 3299 - DirectInput: Incorrect joystick mapping when attaching new joysticks
Jimb Esser
Note: This is using DirectInput, I have to disable XInput as that causes all but the first 4 controllers to be completely ignored by SDL (I can find no way to reconcile XInput devices with DirectInput devices, otherwise I would make a patch that accepts the fifth and later controllers with DirectInput...). XInput does not seem to have the problem below, only DirectInput.
I plug in 3 identical wireless Xbox 360 controllers, call them J1, J2, J3. Direct Input shows them as having GUIDs G1, G2, G3. I unplug J1, then J2 and J3 show up as having GUIDs G1 and G2! Not so "unique"... I start my SDL app when just J2 and J3 are plugged in, and open J2 and J3. Then I plug in a new controller, SDL sees that now G3 exists, assigns that a new SDL joystick instance ID, which I request to be opened, but G3 at this point is J3, which I already had opened! So I end up with two instances of J3 opened, and none of J1. "Re-"opening G1 would get the actual handle to the newly attached controller, but there's no current way to know this. This is clearly a bug or poor design in DirectInput or my wireless receiver drivers, but is a showstopping bug for my 8-20 player games (as soon as any one controller runs out of battery or goes to sleep and gets turned back on, suddenly things are busted requiring a restart (or, at least, a reinitialization of all controllers - the game can't go on)).
The solution I found is to use HID paths instead of GUIDs to uniquely identify joysticks. GUIDs are still needed to open a controller, however I have added code to re-find the GUIDs for all joysticks whenever a new joystick is attached or removed. This does now require opening of all joysticks (instead of just enumerating them), though if your app, like mine, is opening all of them anyway so that any can press a button to join, that doesn't change much (although perhaps they joysticks should be kept open in this case, instead of closed and re-opened). If your app only ever opens one joystick, this will do more work at startup than it did previously.
2017-08-14 03:42:41 +00:00
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
/* We are only supporting HID devices. */
|
|
|
|
CHECK((pDeviceInstance->dwDevType & DIDEVTYPE_HID) != 0);
|
Fixed bug 3299 - DirectInput: Incorrect joystick mapping when attaching new joysticks
Jimb Esser
Note: This is using DirectInput, I have to disable XInput as that causes all but the first 4 controllers to be completely ignored by SDL (I can find no way to reconcile XInput devices with DirectInput devices, otherwise I would make a patch that accepts the fifth and later controllers with DirectInput...). XInput does not seem to have the problem below, only DirectInput.
I plug in 3 identical wireless Xbox 360 controllers, call them J1, J2, J3. Direct Input shows them as having GUIDs G1, G2, G3. I unplug J1, then J2 and J3 show up as having GUIDs G1 and G2! Not so "unique"... I start my SDL app when just J2 and J3 are plugged in, and open J2 and J3. Then I plug in a new controller, SDL sees that now G3 exists, assigns that a new SDL joystick instance ID, which I request to be opened, but G3 at this point is J3, which I already had opened! So I end up with two instances of J3 opened, and none of J1. "Re-"opening G1 would get the actual handle to the newly attached controller, but there's no current way to know this. This is clearly a bug or poor design in DirectInput or my wireless receiver drivers, but is a showstopping bug for my 8-20 player games (as soon as any one controller runs out of battery or goes to sleep and gets turned back on, suddenly things are busted requiring a restart (or, at least, a reinitialization of all controllers - the game can't go on)).
The solution I found is to use HID paths instead of GUIDs to uniquely identify joysticks. GUIDs are still needed to open a controller, however I have added code to re-find the GUIDs for all joysticks whenever a new joystick is attached or removed. This does now require opening of all joysticks (instead of just enumerating them), though if your app, like mine, is opening all of them anyway so that any can press a button to join, that doesn't change much (although perhaps they joysticks should be kept open in this case, instead of closed and re-opened). If your app only ever opens one joystick, this will do more work at startup than it did previously.
2017-08-14 03:42:41 +00:00
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
CHECK(SUCCEEDED(IDirectInput8_CreateDevice(dinput, &pDeviceInstance->guidInstance, &device, NULL)));
|
|
|
|
CHECK(QueryDeviceName(device, &name));
|
|
|
|
CHECK(QueryDevicePath(device, &hidPath));
|
|
|
|
CHECK(QueryDeviceInfo(device, &vendor, &product));
|
Fixed bug 3299 - DirectInput: Incorrect joystick mapping when attaching new joysticks
Jimb Esser
Note: This is using DirectInput, I have to disable XInput as that causes all but the first 4 controllers to be completely ignored by SDL (I can find no way to reconcile XInput devices with DirectInput devices, otherwise I would make a patch that accepts the fifth and later controllers with DirectInput...). XInput does not seem to have the problem below, only DirectInput.
I plug in 3 identical wireless Xbox 360 controllers, call them J1, J2, J3. Direct Input shows them as having GUIDs G1, G2, G3. I unplug J1, then J2 and J3 show up as having GUIDs G1 and G2! Not so "unique"... I start my SDL app when just J2 and J3 are plugged in, and open J2 and J3. Then I plug in a new controller, SDL sees that now G3 exists, assigns that a new SDL joystick instance ID, which I request to be opened, but G3 at this point is J3, which I already had opened! So I end up with two instances of J3 opened, and none of J1. "Re-"opening G1 would get the actual handle to the newly attached controller, but there's no current way to know this. This is clearly a bug or poor design in DirectInput or my wireless receiver drivers, but is a showstopping bug for my 8-20 player games (as soon as any one controller runs out of battery or goes to sleep and gets turned back on, suddenly things are busted requiring a restart (or, at least, a reinitialization of all controllers - the game can't go on)).
The solution I found is to use HID paths instead of GUIDs to uniquely identify joysticks. GUIDs are still needed to open a controller, however I have added code to re-find the GUIDs for all joysticks whenever a new joystick is attached or removed. This does now require opening of all joysticks (instead of just enumerating them), though if your app, like mine, is opening all of them anyway so that any can press a button to join, that doesn't change much (although perhaps they joysticks should be kept open in this case, instead of closed and re-opened). If your app only ever opens one joystick, this will do more work at startup than it did previously.
2017-08-14 03:42:41 +00:00
|
|
|
|
2021-06-10 11:06:32 +00:00
|
|
|
CHECK(!SDL_IsXInputDevice(vendor, product, hidPath));
|
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
pNewJoystick = *(JoyStick_DeviceData**)pContext;
|
2015-06-21 15:33:46 +00:00
|
|
|
while (pNewJoystick) {
|
2021-05-19 14:52:08 +00:00
|
|
|
/* update GUIDs of joysticks with matching paths, in case they're not open yet */
|
|
|
|
if (SDL_strcmp(pNewJoystick->hidPath, hidPath) == 0) {
|
2015-06-21 15:33:46 +00:00
|
|
|
/* if we are replacing the front of the list then update it */
|
2021-05-19 14:52:08 +00:00
|
|
|
if (pNewJoystick == *(JoyStick_DeviceData**)pContext) {
|
|
|
|
*(JoyStick_DeviceData**)pContext = pNewJoystick->pNext;
|
|
|
|
}
|
|
|
|
else if (pPrevJoystick) {
|
2015-06-21 15:33:46 +00:00
|
|
|
pPrevJoystick->pNext = pNewJoystick->pNext;
|
|
|
|
}
|
|
|
|
|
2020-10-27 16:00:42 +00:00
|
|
|
/* Update with new guid/etc, if it has changed */
|
2021-05-19 14:52:08 +00:00
|
|
|
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));
|
Fixed bug 3299 - DirectInput: Incorrect joystick mapping when attaching new joysticks
Jimb Esser
Note: This is using DirectInput, I have to disable XInput as that causes all but the first 4 controllers to be completely ignored by SDL (I can find no way to reconcile XInput devices with DirectInput devices, otherwise I would make a patch that accepts the fifth and later controllers with DirectInput...). XInput does not seem to have the problem below, only DirectInput.
I plug in 3 identical wireless Xbox 360 controllers, call them J1, J2, J3. Direct Input shows them as having GUIDs G1, G2, G3. I unplug J1, then J2 and J3 show up as having GUIDs G1 and G2! Not so "unique"... I start my SDL app when just J2 and J3 are plugged in, and open J2 and J3. Then I plug in a new controller, SDL sees that now G3 exists, assigns that a new SDL joystick instance ID, which I request to be opened, but G3 at this point is J3, which I already had opened! So I end up with two instances of J3 opened, and none of J1. "Re-"opening G1 would get the actual handle to the newly attached controller, but there's no current way to know this. This is clearly a bug or poor design in DirectInput or my wireless receiver drivers, but is a showstopping bug for my 8-20 player games (as soon as any one controller runs out of battery or goes to sleep and gets turned back on, suddenly things are busted requiring a restart (or, at least, a reinitialization of all controllers - the game can't go on)).
The solution I found is to use HID paths instead of GUIDs to uniquely identify joysticks. GUIDs are still needed to open a controller, however I have added code to re-find the GUIDs for all joysticks whenever a new joystick is attached or removed. This does now require opening of all joysticks (instead of just enumerating them), though if your app, like mine, is opening all of them anyway so that any can press a button to join, that doesn't change much (although perhaps they joysticks should be kept open in this case, instead of closed and re-opened). If your app only ever opens one joystick, this will do more work at startup than it did previously.
2017-08-14 03:42:41 +00:00
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
pNewJoystick->pNext = SYS_Joystick;
|
|
|
|
SYS_Joystick = pNewJoystick;
|
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
pNewJoystick = NULL;
|
|
|
|
CHECK(FALSE);
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pPrevJoystick = pNewJoystick;
|
|
|
|
pNewJoystick = pNewJoystick->pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
|
2021-05-19 14:52:08 +00:00
|
|
|
CHECK(pNewJoystick);
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
SDL_zerop(pNewJoystick);
|
2021-05-19 14:52:08 +00:00
|
|
|
SDL_strlcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath));
|
|
|
|
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));
|
2016-11-11 01:19:34 +00:00
|
|
|
SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
|
|
|
|
|
2020-03-13 02:47:30 +00:00
|
|
|
pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
|
2021-05-19 14:52:08 +00:00
|
|
|
CHECK(pNewJoystick->joystickname);
|
2020-03-13 02:47:30 +00:00
|
|
|
|
|
|
|
guid16 = (Uint16 *)pNewJoystick->guid.data;
|
2021-05-19 14:52:08 +00:00
|
|
|
if (vendor && product) {
|
2018-08-09 23:00:17 +00:00
|
|
|
*guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
|
2016-11-11 01:19:34 +00:00
|
|
|
*guid16++ = 0;
|
2018-08-09 23:00:17 +00:00
|
|
|
*guid16++ = SDL_SwapLE16(vendor);
|
2016-11-11 01:19:34 +00:00
|
|
|
*guid16++ = 0;
|
2018-08-09 23:00:17 +00:00
|
|
|
*guid16++ = SDL_SwapLE16(product);
|
2016-11-11 01:19:34 +00:00
|
|
|
*guid16++ = 0;
|
2018-08-09 23:00:17 +00:00
|
|
|
*guid16++ = SDL_SwapLE16(version);
|
2016-11-11 01:19:34 +00:00
|
|
|
*guid16++ = 0;
|
|
|
|
} else {
|
2018-08-09 23:00:17 +00:00
|
|
|
*guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH);
|
2016-11-11 01:19:34 +00:00
|
|
|
*guid16++ = 0;
|
|
|
|
SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
|
|
|
|
}
|
2017-08-09 18:59:29 +00:00
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));
|
2018-08-09 23:00:17 +00:00
|
|
|
|
|
|
|
#ifdef SDL_JOYSTICK_HIDAPI
|
2021-05-19 14:52:08 +00:00
|
|
|
CHECK(!HIDAPI_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname));
|
2018-08-09 23:00:17 +00:00
|
|
|
#endif
|
2016-11-11 01:19:34 +00:00
|
|
|
|
2020-03-16 19:23:38 +00:00
|
|
|
#ifdef SDL_JOYSTICK_RAWINPUT
|
2021-05-19 14:52:08 +00:00
|
|
|
CHECK(!RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname));
|
2020-03-16 19:23:38 +00:00
|
|
|
#endif
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
WINDOWS_AddJoystickDevice(pNewJoystick);
|
2021-05-19 14:52:08 +00:00
|
|
|
pNewJoystick = NULL;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (pNewJoystick) {
|
|
|
|
SDL_free(pNewJoystick->joystickname);
|
|
|
|
SDL_free(pNewJoystick);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_free(hidPath);
|
|
|
|
SDL_free(name);
|
|
|
|
|
|
|
|
if (device) {
|
|
|
|
IDirectInputDevice8_Release(device);
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
return DIENUM_CONTINUE; /* get next device, please */
|
2021-05-19 14:52:08 +00:00
|
|
|
#undef CHECK
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
|
|
|
|
{
|
2021-06-25 21:20:08 +00:00
|
|
|
IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoystickDetectCallback, pContext, DIEDFL_ATTACHEDONLY);
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2021-06-25 21:20:08 +00:00
|
|
|
/* helper function for direct input, gets called for each connected joystick */
|
|
|
|
typedef struct
|
2020-04-23 17:13:17 +00:00
|
|
|
{
|
2021-06-25 21:20:08 +00:00
|
|
|
Uint16 vendor;
|
|
|
|
Uint16 product;
|
|
|
|
SDL_bool present;
|
|
|
|
} Joystick_PresentData;
|
|
|
|
|
|
|
|
static BOOL CALLBACK
|
|
|
|
EnumJoystickPresentCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
|
|
|
|
{
|
2021-11-22 10:16:23 +00:00
|
|
|
#define CHECK(expression) { if(!(expression)) goto err; }
|
2021-06-25 21:20:08 +00:00
|
|
|
Joystick_PresentData *pData = (Joystick_PresentData *)pContext;
|
2020-04-23 17:13:17 +00:00
|
|
|
Uint16 vendor = 0;
|
|
|
|
Uint16 product = 0;
|
2021-06-25 21:20:08 +00:00
|
|
|
LPDIRECTINPUTDEVICE8 device = NULL;
|
2021-11-12 04:35:41 +00:00
|
|
|
BOOL result = DIENUM_CONTINUE;
|
2021-05-19 14:52:08 +00:00
|
|
|
|
2021-06-25 21:20:08 +00:00
|
|
|
/* We are only supporting HID devices. */
|
|
|
|
CHECK((pDeviceInstance->dwDevType & DIDEVTYPE_HID) != 0);
|
2020-04-23 17:13:17 +00:00
|
|
|
|
2021-06-25 21:20:08 +00:00
|
|
|
CHECK(SUCCEEDED(IDirectInput8_CreateDevice(dinput, &pDeviceInstance->guidInstance, &device, NULL)));
|
|
|
|
CHECK(QueryDeviceInfo(device, &vendor, &product));
|
2020-04-23 17:13:17 +00:00
|
|
|
|
2021-06-25 21:20:08 +00:00
|
|
|
if (vendor == pData->vendor && product == pData->product) {
|
|
|
|
pData->present = SDL_TRUE;
|
2021-11-12 04:35:41 +00:00
|
|
|
result = DIENUM_STOP; /* found it */
|
2020-11-12 22:23:56 +00:00
|
|
|
}
|
|
|
|
|
2021-06-25 21:20:08 +00:00
|
|
|
err:
|
|
|
|
if (device) {
|
|
|
|
IDirectInputDevice8_Release(device);
|
|
|
|
}
|
|
|
|
|
2021-11-12 04:35:41 +00:00
|
|
|
return result;
|
2021-06-25 21:20:08 +00:00
|
|
|
#undef CHECK
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_bool
|
|
|
|
SDL_DINPUT_JoystickPresent(Uint16 vendor_id, Uint16 product_id, Uint16 version_number)
|
|
|
|
{
|
|
|
|
Joystick_PresentData data;
|
|
|
|
|
|
|
|
data.vendor = vendor_id;
|
|
|
|
data.product = product_id;
|
|
|
|
data.present = SDL_FALSE;
|
|
|
|
IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoystickPresentCallback, &data, DIEDFL_ATTACHEDONLY);
|
|
|
|
return data.present;
|
2020-04-23 17:13:17 +00:00
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
static BOOL CALLBACK
|
2021-05-19 14:52:08 +00:00
|
|
|
EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE pDeviceObject, LPVOID pContext)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2021-05-19 14:52:08 +00:00
|
|
|
SDL_Joystick *joystick = (SDL_Joystick *)pContext;
|
2015-06-21 15:33:46 +00:00
|
|
|
HRESULT result;
|
|
|
|
input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
|
|
|
|
|
2021-05-19 14:52:08 +00:00
|
|
|
if (pDeviceObject->dwType & DIDFT_BUTTON) {
|
2015-06-21 15:33:46 +00:00
|
|
|
in->type = BUTTON;
|
|
|
|
in->num = joystick->nbuttons;
|
|
|
|
in->ofs = DIJOFS_BUTTON(in->num);
|
|
|
|
joystick->nbuttons++;
|
2021-05-19 14:52:08 +00:00
|
|
|
} else if (pDeviceObject->dwType & DIDFT_POV) {
|
2015-06-21 15:33:46 +00:00
|
|
|
in->type = HAT;
|
|
|
|
in->num = joystick->nhats;
|
|
|
|
in->ofs = DIJOFS_POV(in->num);
|
|
|
|
joystick->nhats++;
|
2021-05-19 14:52:08 +00:00
|
|
|
} else if (pDeviceObject->dwType & DIDFT_AXIS) {
|
2015-06-21 15:33:46 +00:00
|
|
|
DIPROPRANGE diprg;
|
|
|
|
DIPROPDWORD dilong;
|
|
|
|
|
|
|
|
in->type = AXIS;
|
|
|
|
in->num = joystick->naxes;
|
2021-05-19 14:52:08 +00:00
|
|
|
if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_XAxis, sizeof(pDeviceObject->guidType)))
|
2015-06-21 15:33:46 +00:00
|
|
|
in->ofs = DIJOFS_X;
|
2021-05-19 14:52:08 +00:00
|
|
|
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_YAxis, sizeof(pDeviceObject->guidType)))
|
2015-06-21 15:33:46 +00:00
|
|
|
in->ofs = DIJOFS_Y;
|
2021-05-19 14:52:08 +00:00
|
|
|
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_ZAxis, sizeof(pDeviceObject->guidType)))
|
2015-06-21 15:33:46 +00:00
|
|
|
in->ofs = DIJOFS_Z;
|
2021-05-19 14:52:08 +00:00
|
|
|
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RxAxis, sizeof(pDeviceObject->guidType)))
|
2015-06-21 15:33:46 +00:00
|
|
|
in->ofs = DIJOFS_RX;
|
2021-05-19 14:52:08 +00:00
|
|
|
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RyAxis, sizeof(pDeviceObject->guidType)))
|
2015-06-21 15:33:46 +00:00
|
|
|
in->ofs = DIJOFS_RY;
|
2021-05-19 14:52:08 +00:00
|
|
|
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RzAxis, sizeof(pDeviceObject->guidType)))
|
2015-06-21 15:33:46 +00:00
|
|
|
in->ofs = DIJOFS_RZ;
|
2021-05-19 14:52:08 +00:00
|
|
|
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_Slider, sizeof(pDeviceObject->guidType))) {
|
2015-06-21 15:33:46 +00:00
|
|
|
in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
|
|
|
|
++joystick->hwdata->NumSliders;
|
|
|
|
} else {
|
|
|
|
return DIENUM_CONTINUE; /* not an axis we can grok */
|
|
|
|
}
|
|
|
|
|
|
|
|
diprg.diph.dwSize = sizeof(diprg);
|
|
|
|
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
|
2021-05-19 14:52:08 +00:00
|
|
|
diprg.diph.dwObj = pDeviceObject->dwType;
|
2015-06-21 15:33:46 +00:00
|
|
|
diprg.diph.dwHow = DIPH_BYID;
|
2016-12-27 09:39:07 +00:00
|
|
|
diprg.lMin = SDL_JOYSTICK_AXIS_MIN;
|
|
|
|
diprg.lMax = SDL_JOYSTICK_AXIS_MAX;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
|
|
|
DIPROP_RANGE, &diprg.diph);
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return DIENUM_CONTINUE; /* don't use this axis */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set dead zone to 0. */
|
|
|
|
dilong.diph.dwSize = sizeof(dilong);
|
|
|
|
dilong.diph.dwHeaderSize = sizeof(dilong.diph);
|
2021-05-19 14:52:08 +00:00
|
|
|
dilong.diph.dwObj = pDeviceObject->dwType;
|
2015-06-21 15:33:46 +00:00
|
|
|
dilong.diph.dwHow = DIPH_BYID;
|
|
|
|
dilong.dwData = 0;
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
|
|
|
DIPROP_DEADZONE, &dilong.diph);
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return DIENUM_CONTINUE; /* don't use this axis */
|
|
|
|
}
|
|
|
|
|
|
|
|
joystick->naxes++;
|
|
|
|
} else {
|
|
|
|
/* not supported at this time */
|
|
|
|
return DIENUM_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
joystick->hwdata->NumInputs++;
|
|
|
|
|
|
|
|
if (joystick->hwdata->NumInputs == MAX_INPUTS) {
|
|
|
|
return DIENUM_STOP; /* too many */
|
|
|
|
}
|
|
|
|
|
|
|
|
return DIENUM_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sort using the data offset into the DInput struct.
|
|
|
|
* This gives a reasonable ordering for the inputs.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
SortDevFunc(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const input_t *inputA = (const input_t*)a;
|
|
|
|
const input_t *inputB = (const input_t*)b;
|
|
|
|
|
|
|
|
if (inputA->ofs < inputB->ofs)
|
|
|
|
return -1;
|
|
|
|
if (inputA->ofs > inputB->ofs)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sort the input objects and recalculate the indices for each input. */
|
|
|
|
static void
|
|
|
|
SortDevObjects(SDL_Joystick *joystick)
|
|
|
|
{
|
|
|
|
input_t *inputs = joystick->hwdata->Inputs;
|
|
|
|
int nButtons = 0;
|
|
|
|
int nHats = 0;
|
|
|
|
int nAxis = 0;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
|
|
|
|
|
|
|
|
for (n = 0; n < joystick->hwdata->NumInputs; n++) {
|
|
|
|
switch (inputs[n].type) {
|
|
|
|
case BUTTON:
|
|
|
|
inputs[n].num = nButtons;
|
|
|
|
nButtons++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HAT:
|
|
|
|
inputs[n].num = nHats;
|
|
|
|
nHats++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AXIS:
|
|
|
|
inputs[n].num = nAxis;
|
|
|
|
nAxis++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
|
|
|
|
{
|
|
|
|
HRESULT result;
|
|
|
|
DIPROPDWORD dipdw;
|
|
|
|
|
|
|
|
joystick->hwdata->buffered = SDL_TRUE;
|
|
|
|
joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
|
|
|
|
|
|
|
|
SDL_zero(dipdw);
|
|
|
|
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
|
|
|
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
|
|
|
|
|
|
result =
|
|
|
|
IDirectInput8_CreateDevice(dinput,
|
2021-05-19 14:52:08 +00:00
|
|
|
&joystickdevice->dxdevice.guidInstance,
|
|
|
|
&joystick->hwdata->InputDevice,
|
|
|
|
NULL);
|
2015-06-21 15:33:46 +00:00
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInput::CreateDevice", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Acquire shared access. Exclusive access is required for forces,
|
|
|
|
* though. */
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
|
|
|
|
InputDevice, SDL_HelperWindow,
|
|
|
|
DISCL_EXCLUSIVE |
|
|
|
|
DISCL_BACKGROUND);
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use the extended data structure: DIJOYSTATE2. */
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
|
2016-10-01 21:48:18 +00:00
|
|
|
&SDL_c_dfDIJoystick2);
|
2015-06-21 15:33:46 +00:00
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get device capabilities */
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
|
|
|
|
&joystick->hwdata->Capabilities);
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Force capable? */
|
|
|
|
if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
|
|
|
|
result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::Acquire", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset all actuators. */
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
|
|
|
|
InputDevice,
|
|
|
|
DISFFC_RESET);
|
|
|
|
|
|
|
|
/* Not necessarily supported, ignore if not supported.
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
|
|
|
|
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::Unacquire", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Turn on auto-centering for a ForceFeedback device (until told
|
|
|
|
* otherwise). */
|
|
|
|
dipdw.diph.dwObj = 0;
|
|
|
|
dipdw.diph.dwHow = DIPH_DEVICE;
|
|
|
|
dipdw.dwData = DIPROPAUTOCENTER_ON;
|
|
|
|
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
|
|
|
DIPROP_AUTOCENTER, &dipdw.diph);
|
|
|
|
|
|
|
|
/* Not necessarily supported, ignore if not supported.
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SetProperty", result);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/* What buttons and axes does it have? */
|
|
|
|
IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
|
|
|
|
EnumDevObjectsCallback, joystick,
|
|
|
|
DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
|
|
|
|
|
|
|
|
/* Reorder the input objects. Some devices do not report the X axis as
|
|
|
|
* the first axis, for example. */
|
|
|
|
SortDevObjects(joystick);
|
|
|
|
|
|
|
|
dipdw.diph.dwObj = 0;
|
|
|
|
dipdw.diph.dwHow = DIPH_DEVICE;
|
|
|
|
dipdw.dwData = INPUT_QSIZE;
|
|
|
|
|
|
|
|
/* Set the buffer size */
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
|
|
|
DIPROP_BUFFERSIZE, &dipdw.diph);
|
|
|
|
|
|
|
|
if (result == DI_POLLEDDEVICE) {
|
|
|
|
/* This device doesn't support buffering, so we're forced
|
|
|
|
* to use less reliable polling. */
|
|
|
|
joystick->hwdata->buffered = SDL_FALSE;
|
|
|
|
} else if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SetProperty", result);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
static int
|
2020-02-04 20:48:53 +00:00
|
|
|
SDL_DINPUT_JoystickInitRumble(SDL_Joystick * joystick, Sint16 magnitude)
|
2018-08-09 23:00:17 +00:00
|
|
|
{
|
|
|
|
HRESULT result;
|
|
|
|
|
|
|
|
/* Reset and then enable actuators */
|
|
|
|
result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_RESET);
|
|
|
|
if (result == DIERR_INPUTLOST || result == DIERR_NOTEXCLUSIVEACQUIRED) {
|
|
|
|
result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
|
|
|
if (SUCCEEDED(result)) {
|
|
|
|
result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_RESET);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand(DISFFC_RESET)", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->InputDevice, DISFFC_SETACTUATORSON);
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand(DISFFC_SETACTUATORSON)", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the effect */
|
2020-02-04 20:48:53 +00:00
|
|
|
joystick->hwdata->ffeffect = CreateRumbleEffectData(magnitude);
|
2018-08-09 23:00:17 +00:00
|
|
|
if (!joystick->hwdata->ffeffect) {
|
|
|
|
return SDL_OutOfMemory();
|
|
|
|
}
|
|
|
|
|
|
|
|
result = IDirectInputDevice8_CreateEffect(joystick->hwdata->InputDevice, &GUID_Sine,
|
|
|
|
joystick->hwdata->ffeffect, &joystick->hwdata->ffeffect_ref, NULL);
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::CreateEffect", result);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2020-02-04 20:48:53 +00:00
|
|
|
SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
2018-08-09 23:00:17 +00:00
|
|
|
{
|
|
|
|
HRESULT result;
|
|
|
|
|
|
|
|
/* Scale and average the two rumble strengths */
|
|
|
|
Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
|
|
|
|
|
|
|
|
if (!(joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK)) {
|
|
|
|
return SDL_Unsupported();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (joystick->hwdata->ff_initialized) {
|
|
|
|
DIPERIODIC *periodic = ((DIPERIODIC *)joystick->hwdata->ffeffect->lpvTypeSpecificParams);
|
|
|
|
periodic->dwMagnitude = CONVERT_MAGNITUDE(magnitude);
|
|
|
|
|
|
|
|
result = IDirectInputEffect_SetParameters(joystick->hwdata->ffeffect_ref, joystick->hwdata->ffeffect, (DIEP_DURATION | DIEP_TYPESPECIFICPARAMS));
|
|
|
|
if (result == DIERR_INPUTLOST) {
|
|
|
|
result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
|
|
|
if (SUCCEEDED(result)) {
|
|
|
|
result = IDirectInputEffect_SetParameters(joystick->hwdata->ffeffect_ref, joystick->hwdata->ffeffect, (DIEP_DURATION | DIEP_TYPESPECIFICPARAMS));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::SetParameters", result);
|
|
|
|
}
|
|
|
|
} else {
|
2020-02-04 20:48:53 +00:00
|
|
|
if (SDL_DINPUT_JoystickInitRumble(joystick, magnitude) < 0) {
|
2018-08-09 23:00:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
joystick->hwdata->ff_initialized = SDL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = IDirectInputEffect_Start(joystick->hwdata->ffeffect_ref, 1, 0);
|
|
|
|
if (result == DIERR_INPUTLOST || result == DIERR_NOTEXCLUSIVEACQUIRED) {
|
|
|
|
result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
|
|
|
if (SUCCEEDED(result)) {
|
|
|
|
result = IDirectInputEffect_Start(joystick->hwdata->ffeffect_ref, 1, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return SetDIerror("IDirectInputDevice8::Start", result);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-11 17:13:08 +00:00
|
|
|
Uint32
|
|
|
|
SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick * joystick)
|
|
|
|
{
|
2021-11-11 18:12:05 +00:00
|
|
|
Uint32 result = 0;
|
|
|
|
|
|
|
|
if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
|
|
|
|
result |= SDL_JOYCAP_RUMBLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2021-11-11 17:13:08 +00:00
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
static Uint8
|
|
|
|
TranslatePOV(DWORD value)
|
|
|
|
{
|
|
|
|
const int HAT_VALS[] = {
|
|
|
|
SDL_HAT_UP,
|
|
|
|
SDL_HAT_UP | SDL_HAT_RIGHT,
|
|
|
|
SDL_HAT_RIGHT,
|
|
|
|
SDL_HAT_DOWN | SDL_HAT_RIGHT,
|
|
|
|
SDL_HAT_DOWN,
|
|
|
|
SDL_HAT_DOWN | SDL_HAT_LEFT,
|
|
|
|
SDL_HAT_LEFT,
|
|
|
|
SDL_HAT_UP | SDL_HAT_LEFT
|
|
|
|
};
|
|
|
|
|
|
|
|
if (LOWORD(value) == 0xFFFF)
|
|
|
|
return SDL_HAT_CENTERED;
|
|
|
|
|
|
|
|
/* Round the value up: */
|
|
|
|
value += 4500 / 2;
|
|
|
|
value %= 36000;
|
|
|
|
value /= 4500;
|
|
|
|
|
|
|
|
if (value >= 8)
|
|
|
|
return SDL_HAT_CENTERED; /* shouldn't happen */
|
|
|
|
|
|
|
|
return HAT_VALS[value];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function to update the state of a joystick - called as a device poll.
|
|
|
|
* This function shouldn't update the joystick structure directly,
|
|
|
|
* but instead should call SDL_PrivateJoystick*() to deliver events
|
|
|
|
* and update joystick device state.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
|
|
|
|
{
|
|
|
|
DIJOYSTATE2 state;
|
|
|
|
HRESULT result;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
|
|
|
|
sizeof(DIJOYSTATE2), &state);
|
|
|
|
if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
|
|
|
|
IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
|
|
|
|
sizeof(DIJOYSTATE2), &state);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result != DI_OK) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set each known axis, button and POV. */
|
|
|
|
for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
|
|
|
|
const input_t *in = &joystick->hwdata->Inputs[i];
|
|
|
|
|
|
|
|
switch (in->type) {
|
|
|
|
case AXIS:
|
|
|
|
switch (in->ofs) {
|
|
|
|
case DIJOFS_X:
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
|
|
|
|
break;
|
|
|
|
case DIJOFS_Y:
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
|
|
|
|
break;
|
|
|
|
case DIJOFS_Z:
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
|
|
|
|
break;
|
|
|
|
case DIJOFS_RX:
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
|
|
|
|
break;
|
|
|
|
case DIJOFS_RY:
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
|
|
|
|
break;
|
|
|
|
case DIJOFS_RZ:
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
|
|
|
|
break;
|
|
|
|
case DIJOFS_SLIDER(0):
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
|
|
|
|
break;
|
|
|
|
case DIJOFS_SLIDER(1):
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BUTTON:
|
|
|
|
SDL_PrivateJoystickButton(joystick, in->num,
|
|
|
|
(Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
|
|
|
|
break;
|
|
|
|
case HAT:
|
|
|
|
{
|
|
|
|
Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
|
|
|
|
SDL_PrivateJoystickHat(joystick, in->num, pos);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-24 22:58:33 +00:00
|
|
|
static void
|
|
|
|
UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
HRESULT result;
|
|
|
|
DWORD numevents;
|
|
|
|
DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
|
|
|
|
|
|
|
|
numevents = INPUT_QSIZE;
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
|
|
|
|
sizeof(DIDEVICEOBJECTDATA), evtbuf,
|
|
|
|
&numevents, 0);
|
|
|
|
if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
|
|
|
|
IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
|
|
|
result =
|
|
|
|
IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
|
|
|
|
sizeof(DIDEVICEOBJECTDATA),
|
|
|
|
evtbuf, &numevents, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle the events or punt */
|
|
|
|
if (FAILED(result)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < (int)numevents; ++i) {
|
|
|
|
int j;
|
|
|
|
|
|
|
|
for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
|
|
|
|
const input_t *in = &joystick->hwdata->Inputs[j];
|
|
|
|
|
|
|
|
if (evtbuf[i].dwOfs != in->ofs)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (in->type) {
|
|
|
|
case AXIS:
|
|
|
|
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
|
|
|
|
break;
|
|
|
|
case BUTTON:
|
|
|
|
SDL_PrivateJoystickButton(joystick, in->num,
|
|
|
|
(Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
|
|
|
|
break;
|
|
|
|
case HAT:
|
|
|
|
{
|
|
|
|
Uint8 pos = TranslatePOV(evtbuf[i].dwData);
|
|
|
|
SDL_PrivateJoystickHat(joystick, in->num, pos);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == DI_BUFFEROVERFLOW) {
|
|
|
|
/* Our buffer wasn't big enough to hold all the queued events,
|
|
|
|
* so poll the device to make sure we have the complete state.
|
|
|
|
*/
|
|
|
|
UpdateDINPUTJoystickState_Polled(joystick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
|
|
|
{
|
|
|
|
HRESULT result;
|
|
|
|
|
|
|
|
result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
|
|
|
|
if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
|
|
|
|
IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
|
|
|
IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (joystick->hwdata->buffered) {
|
|
|
|
UpdateDINPUTJoystickState_Buffered(joystick);
|
|
|
|
} else {
|
|
|
|
UpdateDINPUTJoystickState_Polled(joystick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
|
|
|
|
{
|
2018-08-09 23:00:17 +00:00
|
|
|
if (joystick->hwdata->ffeffect_ref) {
|
|
|
|
IDirectInputEffect_Unload(joystick->hwdata->ffeffect_ref);
|
|
|
|
joystick->hwdata->ffeffect_ref = NULL;
|
|
|
|
}
|
|
|
|
if (joystick->hwdata->ffeffect) {
|
|
|
|
FreeRumbleEffectData(joystick->hwdata->ffeffect);
|
|
|
|
joystick->hwdata->ffeffect = NULL;
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
|
|
|
|
IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
|
2018-08-09 23:00:17 +00:00
|
|
|
joystick->hwdata->ff_initialized = SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickQuit(void)
|
|
|
|
{
|
|
|
|
if (dinput != NULL) {
|
|
|
|
IDirectInput8_Release(dinput);
|
|
|
|
dinput = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coinitialized) {
|
|
|
|
WIN_CoUninitialize();
|
|
|
|
coinitialized = SDL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* !SDL_JOYSTICK_DINPUT */
|
|
|
|
|
|
|
|
typedef struct JoyStick_DeviceData JoyStick_DeviceData;
|
|
|
|
|
|
|
|
int
|
|
|
|
SDL_DINPUT_JoystickInit(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-04-23 17:13:17 +00:00
|
|
|
SDL_bool
|
|
|
|
SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
|
|
|
|
{
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
int
|
|
|
|
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
|
|
|
|
{
|
|
|
|
return SDL_Unsupported();
|
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
int
|
2020-02-04 20:48:53 +00:00
|
|
|
SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
2018-08-09 23:00:17 +00:00
|
|
|
{
|
|
|
|
return SDL_Unsupported();
|
|
|
|
}
|
|
|
|
|
2021-11-11 17:13:08 +00:00
|
|
|
Uint32
|
|
|
|
SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick * joystick)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_DINPUT_JoystickQuit(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* SDL_JOYSTICK_DINPUT */
|
|
|
|
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|