SDL_dinputjoystick.c 52 KB

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