| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
- 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"
- #include "SDL_xinputjoystick_c.h"
- #include "../hidapi/SDL_hidapijoystick_c.h"
- #ifndef DIDFT_OPTIONAL
- #define DIDFT_OPTIONAL 0x80000000
- #endif
- #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
- #define JOY_AXIS_THRESHOLD (((SDL_JOYSTICK_AXIS_MAX)-(SDL_JOYSTICK_AXIS_MIN))/100) /* 1% motion */
- #define CONVERT_MAGNITUDE(x) (((x)*10000) / 0x7FFF)
- /* external variables referenced. */
- extern HWND SDL_HelperWindow;
- /* local variables */
- static SDL_bool coinitialized = SDL_FALSE;
- static LPDIRECTINPUT8 dinput = NULL;
- static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
- static UINT SDL_RawDevListCount = 0;
- /* Taken from Wine - Thanks! */
- static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
- { &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &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 },
- { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
- };
- const DIDATAFORMAT SDL_c_dfDIJoystick2 = {
- 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() [%s]: %s", function,
- DXGetErrorString9A(code), DXGetErrorDescription9A(code));
- */
- return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code);
- }
- static SDL_bool
- SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
- {
- static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_XOneWiredGamepad = { MAKELONG(0x045E, 0x02FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_XOneWirelessGamepad = { MAKELONG(0x045E, 0x02DD), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_XOneNewWirelessGamepad = { MAKELONG(0x045E, 0x02D1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_XOneSWirelessGamepad = { MAKELONG(0x045E, 0x02EA), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_XOneSBluetoothGamepad = { MAKELONG(0x045E, 0x02E0), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static GUID IID_XOneEliteWirelessGamepad = { MAKELONG(0x045E, 0x02E3), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
- static const GUID *s_XInputProductGUID[] = {
- &IID_ValveStreamingGamepad,
- &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
- &IID_X360WirelessGamepad, /* Microsoft's wireless X360 controller for Windows. */
- &IID_XOneWiredGamepad, /* Microsoft's wired Xbox One controller for Windows. */
- &IID_XOneWirelessGamepad, /* Microsoft's wireless Xbox One controller for Windows. */
- &IID_XOneNewWirelessGamepad, /* Microsoft's updated wireless Xbox One controller (w/ 3.5 mm jack) for Windows. */
- &IID_XOneSWirelessGamepad, /* Microsoft's wireless Xbox One S controller for Windows. */
- &IID_XOneSBluetoothGamepad, /* Microsoft's Bluetooth Xbox One S controller for Windows. */
- &IID_XOneEliteWirelessGamepad /* Microsoft's wireless Xbox One Elite controller for Windows. */
- };
- size_t iDevice;
- UINT i;
- if (!SDL_XINPUT_Enabled()) {
- return SDL_FALSE;
- }
- /* Check for well known XInput device GUIDs */
- /* 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. */
- for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
- if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
- return SDL_TRUE;
- }
- }
- /* Go through RAWINPUT (WinXP and later) to find HID devices. */
- /* Cache this if we end up using it. */
- if (SDL_RawDevList == NULL) {
- if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
- return SDL_FALSE; /* oh well. */
- }
- SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
- if (SDL_RawDevList == NULL) {
- SDL_OutOfMemory();
- return SDL_FALSE;
- }
- if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
- SDL_free(SDL_RawDevList);
- SDL_RawDevList = NULL;
- return SDL_FALSE; /* oh well. */
- }
- }
- for (i = 0; i < SDL_RawDevListCount; i++) {
- RID_DEVICE_INFO rdi;
- char devName[128];
- UINT rdiSize = sizeof(rdi);
- UINT nameSize = SDL_arraysize(devName);
- rdi.cbSize = sizeof(rdi);
- if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
- (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
- (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
- (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
- (SDL_strstr(devName, "IG_") != NULL)) {
- return SDL_TRUE;
- }
- }
- return SDL_FALSE;
- }
- void FreeRumbleEffectData(DIEFFECT *effect)
- {
- if (!effect) {
- return;
- }
- SDL_free(effect->rgdwAxes);
- SDL_free(effect->rglDirection);
- SDL_free(effect->lpvTypeSpecificParams);
- SDL_free(effect);
- }
- DIEFFECT *CreateRumbleEffectData(Sint16 magnitude, Uint32 duration_ms)
- {
- 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;
- effect->dwDuration = duration_ms * 1000; /* In microseconds. */
- 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;
- }
- 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,
- &IID_IDirectInput8, (LPVOID)&dinput);
- if (FAILED(result)) {
- return SetDIerror("CoCreateInstance", result);
- }
- /* Because we used CoCreateInstance, we need to Initialize it, first. */
- instance = GetModuleHandle(NULL);
- if (instance == NULL) {
- return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
- }
- result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
- if (FAILED(result)) {
- return SetDIerror("IDirectInput::Initialize", result);
- }
- return 0;
- }
- /* helper function for direct input, gets called for each connected joystick */
- static BOOL CALLBACK
- EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
- {
- JoyStick_DeviceData *pNewJoystick;
- JoyStick_DeviceData *pPrevJoystick = NULL;
- const DWORD devtype = (pdidInstance->dwDevType & 0xFF);
- Uint16 *guid16;
- Uint16 vendor = 0;
- Uint16 product = 0;
- Uint16 version = 0;
- WCHAR hidPath[MAX_PATH];
- if (devtype == DI8DEVTYPE_SUPPLEMENTAL) {
- /* Add any supplemental devices that should be ignored here */
- #define MAKE_TABLE_ENTRY(VID, PID) ((((DWORD)PID)<<16)|VID)
- static DWORD ignored_devices[] = {
- MAKE_TABLE_ENTRY(0, 0)
- };
- #undef MAKE_TABLE_ENTRY
- unsigned int i;
- for (i = 0; i < SDL_arraysize(ignored_devices); ++i) {
- if (pdidInstance->guidProduct.Data1 == ignored_devices[i]) {
- return DIENUM_CONTINUE;
- }
- }
- }
- if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
- return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
- }
- {
- HRESULT result;
- LPDIRECTINPUTDEVICE8 device;
- LPDIRECTINPUTDEVICE8 InputDevice;
- DIPROPGUIDANDPATH dipdw2;
- result = IDirectInput8_CreateDevice(dinput, &(pdidInstance->guidInstance), &device, NULL);
- if (FAILED(result)) {
- return DIENUM_CONTINUE; /* better luck next time? */
- }
- /* Now get the IDirectInputDevice8 interface, instead. */
- result = IDirectInputDevice8_QueryInterface(device, &IID_IDirectInputDevice8, (LPVOID *)&InputDevice);
- /* We are done with this object. Use the stored one from now on. */
- IDirectInputDevice8_Release(device);
- if (FAILED(result)) {
- return DIENUM_CONTINUE; /* better luck next time? */
- }
- dipdw2.diph.dwSize = sizeof(dipdw2);
- dipdw2.diph.dwHeaderSize = sizeof(dipdw2.diph);
- dipdw2.diph.dwObj = 0; // device property
- dipdw2.diph.dwHow = DIPH_DEVICE;
- result = IDirectInputDevice8_GetProperty(InputDevice, DIPROP_GUIDANDPATH, &dipdw2.diph);
- IDirectInputDevice8_Release(InputDevice);
- if (FAILED(result)) {
- return DIENUM_CONTINUE; /* better luck next time? */
- }
- /* Get device path, compare that instead of GUID, additionally update GUIDs of joysticks with matching paths, in case they're not open yet. */
- SDL_wcslcpy(hidPath, dipdw2.wszPath, SDL_arraysize(hidPath));
- }
- pNewJoystick = *(JoyStick_DeviceData **)pContext;
- while (pNewJoystick) {
- if (SDL_wcscmp(pNewJoystick->hidPath, hidPath) == 0) {
- /* if we are replacing the front of the list then update it */
- if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
- *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
- } else if (pPrevJoystick) {
- pPrevJoystick->pNext = pNewJoystick->pNext;
- }
- // Update with new guid/etc, if it has changed
- pNewJoystick->dxdevice = *pdidInstance;
- pNewJoystick->pNext = SYS_Joystick;
- SYS_Joystick = pNewJoystick;
- return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
- }
- pPrevJoystick = pNewJoystick;
- pNewJoystick = pNewJoystick->pNext;
- }
- pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
- if (!pNewJoystick) {
- return DIENUM_CONTINUE; /* better luck next time? */
- }
- SDL_zerop(pNewJoystick);
- SDL_wcslcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath));
- pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
- if (!pNewJoystick->joystickname) {
- SDL_free(pNewJoystick);
- return DIENUM_CONTINUE; /* better luck next time? */
- }
- SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE));
- SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
- guid16 = (Uint16 *)pNewJoystick->guid.data;
- if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
- vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
- product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
- version = 0;
- *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
- *guid16++ = 0;
- *guid16++ = SDL_SwapLE16(vendor);
- *guid16++ = 0;
- *guid16++ = SDL_SwapLE16(product);
- *guid16++ = 0;
- *guid16++ = SDL_SwapLE16(version);
- *guid16++ = 0;
- } else {
- *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH);
- *guid16++ = 0;
- SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
- }
- if (SDL_strstr(pNewJoystick->joystickname, " XINPUT ") != NULL) {
- /* This is a duplicate interface for a controller that will show up with XInput,
- e.g. Xbox One Elite Series 2 in Bluetooth mode.
- */
- SDL_free(pNewJoystick->joystickname);
- SDL_free(pNewJoystick);
- return DIENUM_CONTINUE;
- }
- if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
- SDL_free(pNewJoystick->joystickname);
- SDL_free(pNewJoystick);
- return DIENUM_CONTINUE;
- }
- #ifdef SDL_JOYSTICK_HIDAPI
- if (HIDAPI_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) {
- /* The HIDAPI driver is taking care of this device */
- SDL_free(pNewJoystick->joystickname);
- SDL_free(pNewJoystick);
- return DIENUM_CONTINUE;
- }
- #endif
- WINDOWS_AddJoystickDevice(pNewJoystick);
- return DIENUM_CONTINUE; /* get next device, please */
- }
- void
- SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
- {
- IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
- if (SDL_RawDevList) {
- SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */
- SDL_RawDevList = NULL;
- }
- SDL_RawDevListCount = 0;
- }
- static BOOL CALLBACK
- EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
- {
- SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
- HRESULT result;
- input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
- if (dev->dwType & DIDFT_BUTTON) {
- in->type = BUTTON;
- in->num = joystick->nbuttons;
- in->ofs = DIJOFS_BUTTON(in->num);
- joystick->nbuttons++;
- } else if (dev->dwType & DIDFT_POV) {
- in->type = HAT;
- in->num = joystick->nhats;
- in->ofs = DIJOFS_POV(in->num);
- joystick->nhats++;
- } else if (dev->dwType & DIDFT_AXIS) {
- DIPROPRANGE diprg;
- DIPROPDWORD dilong;
- in->type = AXIS;
- in->num = joystick->naxes;
- if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_X;
- else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_Y;
- else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_Z;
- else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_RX;
- else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_RY;
- else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
- in->ofs = DIJOFS_RZ;
- else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
- 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);
- diprg.diph.dwObj = dev->dwType;
- diprg.diph.dwHow = DIPH_BYID;
- diprg.lMin = SDL_JOYSTICK_AXIS_MIN;
- diprg.lMax = SDL_JOYSTICK_AXIS_MAX;
- 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);
- dilong.diph.dwObj = dev->dwType;
- 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;
- LPDIRECTINPUTDEVICE8 device;
- 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,
- &(joystickdevice->dxdevice.guidInstance), &device, NULL);
- if (FAILED(result)) {
- return SetDIerror("IDirectInput::CreateDevice", result);
- }
- /* Now get the IDirectInputDevice8 interface, instead. */
- result = IDirectInputDevice8_QueryInterface(device,
- &IID_IDirectInputDevice8,
- (LPVOID *)& joystick->
- hwdata->InputDevice);
- /* We are done with this object. Use the stored one from now on. */
- IDirectInputDevice8_Release(device);
- if (FAILED(result)) {
- return SetDIerror("IDirectInputDevice8::QueryInterface", 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,
- &SDL_c_dfDIJoystick2);
- 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;
- }
- static int
- SDL_DINPUT_JoystickInitRumble(SDL_Joystick * joystick, Sint16 magnitude, Uint32 duration_ms)
- {
- 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 */
- joystick->hwdata->ffeffect = CreateRumbleEffectData(magnitude, duration_ms);
- 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
- SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
- {
- 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);
- joystick->hwdata->ffeffect->dwDuration = duration_ms * 1000; /* In microseconds. */
- 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 {
- if (SDL_DINPUT_JoystickInitRumble(joystick, magnitude, duration_ms) < 0) {
- 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;
- }
- 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];
- }
- 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;
- }
- }
- }
- }
- /* 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;
- }
- }
- }
- }
- 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)
- {
- 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;
- }
- IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
- IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
- joystick->hwdata->ff_initialized = SDL_FALSE;
- }
- 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)
- {
- }
- int
- SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
- {
- return SDL_Unsupported();
- }
- int
- SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
- {
- return SDL_Unsupported();
- }
- 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: */
|