SDL_hidapi_wii.c 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2021 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. #ifdef SDL_JOYSTICK_HIDAPI
  20. #include "SDL_hints.h"
  21. #include "SDL_events.h"
  22. #include "SDL_timer.h"
  23. #include "SDL_joystick.h"
  24. #include "SDL_gamecontroller.h"
  25. #include "../../SDL_hints_c.h"
  26. #include "../SDL_sysjoystick.h"
  27. #include "SDL_hidapijoystick_c.h"
  28. #include "SDL_hidapi_rumble.h"
  29. #include "SDL_hidapi_nintendo.h"
  30. #ifdef SDL_JOYSTICK_HIDAPI_WII
  31. /* Define this if you want to log all packets from the controller */
  32. /*#define DEBUG_WII_PROTOCOL*/
  33. #define ENABLE_CONTINUOUS_REPORTING SDL_TRUE
  34. #define INPUT_WAIT_TIMEOUT_MS (3 * 1000)
  35. #define MOTION_PLUS_UPDATE_TIME_MS (8 * 1000)
  36. #define STATUS_UPDATE_TIME_MS (15 * 60 * 1000)
  37. #define WII_EXTENSION_NONE 0x2E2E
  38. #define WII_EXTENSION_UNINITIALIZED 0xFFFF
  39. #define WII_EXTENSION_NUNCHUK 0x0000
  40. #define WII_EXTENSION_GAMEPAD 0x0101
  41. #define WII_EXTENSION_WIIUPRO 0x0120
  42. #define WII_EXTENSION_MOTIONPLUS_MASK 0xF0FF
  43. #define WII_EXTENSION_MOTIONPLUS_ID 0x0005
  44. #define WII_MOTIONPLUS_MODE_NONE 0x00
  45. #define WII_MOTIONPLUS_MODE_STANDARD 0x04
  46. #define WII_MOTIONPLUS_MODE_NUNCHUK 0x05
  47. #define WII_MOTIONPLUS_MODE_GAMEPAD 0x07
  48. typedef enum {
  49. k_eWiiInputReportIDs_Status = 0x20,
  50. k_eWiiInputReportIDs_ReadMemory = 0x21,
  51. k_eWiiInputReportIDs_Acknowledge = 0x22,
  52. k_eWiiInputReportIDs_ButtonData0 = 0x30,
  53. k_eWiiInputReportIDs_ButtonData1 = 0x31,
  54. k_eWiiInputReportIDs_ButtonData2 = 0x32,
  55. k_eWiiInputReportIDs_ButtonData3 = 0x33,
  56. k_eWiiInputReportIDs_ButtonData4 = 0x34,
  57. k_eWiiInputReportIDs_ButtonData5 = 0x35,
  58. k_eWiiInputReportIDs_ButtonData6 = 0x36,
  59. k_eWiiInputReportIDs_ButtonData7 = 0x37,
  60. k_eWiiInputReportIDs_ButtonDataD = 0x3D,
  61. k_eWiiInputReportIDs_ButtonDataE = 0x3E,
  62. k_eWiiInputReportIDs_ButtonDataF = 0x3F,
  63. } EWiiInputReportIDs;
  64. typedef enum {
  65. k_eWiiOutputReportIDs_Rumble = 0x10,
  66. k_eWiiOutputReportIDs_LEDs = 0x11,
  67. k_eWiiOutputReportIDs_DataReportingMode = 0x12,
  68. k_eWiiOutputReportIDs_IRCameraEnable = 0x13,
  69. k_eWiiOutputReportIDs_SpeakerEnable = 0x14,
  70. k_eWiiOutputReportIDs_StatusRequest = 0x15,
  71. k_eWiiOutputReportIDs_WriteMemory = 0x16,
  72. k_eWiiOutputReportIDs_ReadMemory = 0x17,
  73. k_eWiiOutputReportIDs_SpeakerData = 0x18,
  74. k_eWiiOutputReportIDs_SpeakerMute = 0x19,
  75. k_eWiiOutputReportIDs_IRCameraEnable2 = 0x1a,
  76. } EWiiOutputReportIDs;
  77. typedef enum {
  78. k_eWiiPlayerLEDs_P1 = 0x10,
  79. k_eWiiPlayerLEDs_P2 = 0x20,
  80. k_eWiiPlayerLEDs_P3 = 0x40,
  81. k_eWiiPlayerLEDs_P4 = 0x80,
  82. } EWiiPlayerLEDs;
  83. typedef enum {
  84. k_eWiiCommunicationState_None, /* No special communications happening */
  85. k_eWiiCommunicationState_CheckMotionPlusStage1, /* Sent standard extension identify request */
  86. k_eWiiCommunicationState_CheckMotionPlusStage2, /* Sent Motion Plus extension identify request */
  87. } EWiiCommunicationState;
  88. typedef enum {
  89. k_eWiiButtons_A = SDL_CONTROLLER_BUTTON_MISC1,
  90. k_eWiiButtons_B,
  91. k_eWiiButtons_One,
  92. k_eWiiButtons_Two,
  93. k_eWiiButtons_Plus,
  94. k_eWiiButtons_Minus,
  95. k_eWiiButtons_Home,
  96. k_eWiiButtons_DPad_Up,
  97. k_eWiiButtons_DPad_Down,
  98. k_eWiiButtons_DPad_Left,
  99. k_eWiiButtons_DPad_Right,
  100. k_eWiiButtons_Max
  101. } EWiiButtons;
  102. #define k_unWiiPacketDataLength 22
  103. typedef struct {
  104. Uint8 rgucBaseButtons[2];
  105. Uint8 rgucAccelerometer[3];
  106. Uint8 rgucExtension[21];
  107. SDL_bool hasBaseButtons;
  108. SDL_bool hasAccelerometer;
  109. Uint8 ucNExtensionBytes;
  110. } WiiButtonData;
  111. typedef struct {
  112. SDL_HIDAPI_Device *device;
  113. SDL_Joystick *joystick;
  114. EWiiCommunicationState m_eCommState;
  115. EWiiExtensionControllerType m_eExtensionControllerType;
  116. SDL_bool m_bUseButtonLabels;
  117. SDL_bool m_bPlayerLights;
  118. int m_nPlayerIndex;
  119. SDL_bool m_bRumbleActive;
  120. SDL_bool m_bMotionPlusPresent;
  121. Uint8 m_ucMotionPlusMode;
  122. SDL_bool m_bReportSensors;
  123. Uint8 m_rgucReadBuffer[k_unWiiPacketDataLength];
  124. Uint32 m_unLastInput;
  125. Uint32 m_unLastStatus;
  126. Uint32 m_unNextMotionPlusCheck;
  127. SDL_bool m_bDisconnected;
  128. struct StickCalibrationData {
  129. Uint16 min;
  130. Uint16 max;
  131. Uint16 center;
  132. Uint16 deadzone;
  133. } m_StickCalibrationData[6];
  134. } SDL_DriverWii_Context;
  135. static void
  136. HIDAPI_DriverWii_RegisterHints(SDL_HintCallback callback, void *userdata)
  137. {
  138. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII, callback, userdata);
  139. }
  140. static void
  141. HIDAPI_DriverWii_UnregisterHints(SDL_HintCallback callback, void *userdata)
  142. {
  143. SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII, callback, userdata);
  144. }
  145. static SDL_bool
  146. HIDAPI_DriverWii_IsEnabled(void)
  147. {
  148. return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_WII,
  149. SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
  150. SDL_HIDAPI_DEFAULT));
  151. }
  152. static SDL_bool
  153. HIDAPI_DriverWii_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
  154. {
  155. if (vendor_id == USB_VENDOR_NINTENDO &&
  156. (product_id == USB_PRODUCT_NINTENDO_WII_REMOTE ||
  157. product_id == USB_PRODUCT_NINTENDO_WII_REMOTE2)) {
  158. return SDL_TRUE;
  159. }
  160. return SDL_FALSE;
  161. }
  162. static int ReadInput(SDL_DriverWii_Context *ctx)
  163. {
  164. int size;
  165. /* Make sure we don't try to read at the same time a write is happening */
  166. if (SDL_AtomicGet(&ctx->device->rumble_pending) > 0) {
  167. return 0;
  168. }
  169. size = SDL_hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
  170. #ifdef DEBUG_WII_PROTOCOL
  171. if (size > 0) {
  172. HIDAPI_DumpPacket("Wii packet: size = %d", ctx->m_rgucReadBuffer, size);
  173. }
  174. #endif
  175. return size;
  176. }
  177. static SDL_bool WriteOutput(SDL_DriverWii_Context *ctx, const Uint8 *data, int size, SDL_bool sync)
  178. {
  179. #ifdef DEBUG_WII_PROTOCOL
  180. if (size > 0) {
  181. HIDAPI_DumpPacket("Wii write packet: size = %d", data, size);
  182. }
  183. #endif
  184. if (sync) {
  185. return (SDL_hid_write(ctx->device->dev, data, size) >= 0);
  186. } else {
  187. /* Use the rumble thread for general asynchronous writes */
  188. if (SDL_HIDAPI_LockRumble() < 0) {
  189. return SDL_FALSE;
  190. }
  191. return (SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size) >= 0);
  192. }
  193. }
  194. static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs expectedID, SDL_bool(*isMine)(const Uint8 *))
  195. {
  196. Uint32 TimeoutMs = 250; /* Seeing successful reads after about 200 ms */
  197. Uint32 startTicks = SDL_GetTicks();
  198. int nRead = 0;
  199. while ((nRead = ReadInput(ctx)) != -1) {
  200. if (nRead > 0) {
  201. if (ctx->m_rgucReadBuffer[0] == expectedID && (!isMine || isMine(ctx->m_rgucReadBuffer))) {
  202. return SDL_TRUE;
  203. }
  204. } else {
  205. if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) {
  206. break;
  207. }
  208. SDL_Delay(1);
  209. }
  210. }
  211. SDL_SetError("Read timed out");
  212. return SDL_FALSE;
  213. }
  214. static SDL_bool IsWriteMemoryResponse(const Uint8 *data)
  215. {
  216. return data[3] == k_eWiiOutputReportIDs_WriteMemory;
  217. }
  218. static SDL_bool WriteRegister(SDL_DriverWii_Context *ctx, Uint32 address, const Uint8 *data, int size, SDL_bool sync)
  219. {
  220. Uint8 writeRequest[k_unWiiPacketDataLength];
  221. SDL_zeroa(writeRequest);
  222. writeRequest[0] = k_eWiiOutputReportIDs_WriteMemory;
  223. writeRequest[1] = 0x04 | ctx->m_bRumbleActive;
  224. writeRequest[2] = (address >> 16) & 0xff;
  225. writeRequest[3] = (address >> 8) & 0xff;
  226. writeRequest[4] = address & 0xff;
  227. writeRequest[5] = size;
  228. SDL_assert(size > 0 && size <= 16);
  229. SDL_memcpy(writeRequest + 6, data, size);
  230. if (!WriteOutput(ctx, writeRequest, sizeof(writeRequest), sync)) {
  231. return SDL_FALSE;
  232. }
  233. if (sync) {
  234. /* Wait for response */
  235. if (!ReadInputSync(ctx, k_eWiiInputReportIDs_Acknowledge, IsWriteMemoryResponse)) {
  236. return SDL_FALSE;
  237. }
  238. if (ctx->m_rgucReadBuffer[4]) {
  239. SDL_SetError("Write memory failed: %d", ctx->m_rgucReadBuffer[4]);
  240. return SDL_FALSE;
  241. }
  242. }
  243. return SDL_TRUE;
  244. }
  245. static SDL_bool ReadRegister(SDL_DriverWii_Context *ctx, Uint32 address, int size, SDL_bool sync)
  246. {
  247. Uint8 readRequest[7];
  248. readRequest[0] = k_eWiiOutputReportIDs_ReadMemory;
  249. readRequest[1] = 0x04 | ctx->m_bRumbleActive;
  250. readRequest[2] = (address >> 16) & 0xff;
  251. readRequest[3] = (address >> 8) & 0xff;
  252. readRequest[4] = address & 0xff;
  253. readRequest[5] = (size >> 8) & 0xff;
  254. readRequest[6] = size & 0xff;
  255. SDL_assert(size > 0 && size <= 0xffff);
  256. if (!WriteOutput(ctx, readRequest, sizeof(readRequest), sync)) {
  257. return SDL_FALSE;
  258. }
  259. if (sync) {
  260. SDL_assert(size <= 16); /* Only waiting for one packet is supported right now */
  261. /* Wait for response */
  262. if (!ReadInputSync(ctx, k_eWiiInputReportIDs_ReadMemory, NULL)) {
  263. return SDL_FALSE;
  264. }
  265. }
  266. return SDL_TRUE;
  267. }
  268. static SDL_bool SendExtensionIdentify(SDL_DriverWii_Context *ctx, SDL_bool sync)
  269. {
  270. return ReadRegister(ctx, 0xA400FE, 2, sync);
  271. }
  272. static SDL_bool ParseExtensionIdentifyResponse(SDL_DriverWii_Context *ctx, Uint16 *extension)
  273. {
  274. int i;
  275. if (ctx->m_rgucReadBuffer[0] != k_eWiiInputReportIDs_ReadMemory) {
  276. SDL_SetError("Unexpected extension response type");
  277. return SDL_FALSE;
  278. }
  279. if (ctx->m_rgucReadBuffer[4] != 0x00 || ctx->m_rgucReadBuffer[5] != 0xFE) {
  280. SDL_SetError("Unexpected extension response address");
  281. return SDL_FALSE;
  282. }
  283. if (ctx->m_rgucReadBuffer[3] != 0x10) {
  284. Uint8 error = (ctx->m_rgucReadBuffer[3] & 0xF);
  285. if (error == 7) {
  286. /* The extension memory isn't mapped */
  287. *extension = WII_EXTENSION_NONE;
  288. return SDL_TRUE;
  289. }
  290. if (error) {
  291. SDL_SetError("Failed to read extension type: %d", error);
  292. } else {
  293. SDL_SetError("Unexpected read length when reading extension type: %d", (ctx->m_rgucReadBuffer[3] >> 4) + 1);
  294. }
  295. return SDL_FALSE;
  296. }
  297. *extension = 0;
  298. for (i = 6; i < 8; i++) {
  299. *extension = *extension << 8 | ctx->m_rgucReadBuffer[i];
  300. }
  301. return SDL_TRUE;
  302. }
  303. static EWiiExtensionControllerType GetExtensionType(Uint16 extension_id)
  304. {
  305. switch (extension_id) {
  306. case WII_EXTENSION_NONE:
  307. return k_eWiiExtensionControllerType_None;
  308. case WII_EXTENSION_NUNCHUK:
  309. return k_eWiiExtensionControllerType_Nunchuk;
  310. case WII_EXTENSION_GAMEPAD:
  311. return k_eWiiExtensionControllerType_Gamepad;
  312. case WII_EXTENSION_WIIUPRO:
  313. return k_eWiiExtensionControllerType_WiiUPro;
  314. default:
  315. return k_eWiiExtensionControllerType_Unknown;
  316. }
  317. }
  318. static SDL_bool SendExtensionReset(SDL_DriverWii_Context *ctx, SDL_bool sync)
  319. {
  320. SDL_bool result = SDL_TRUE;
  321. {
  322. Uint8 data = 0x55;
  323. result = result && WriteRegister(ctx, 0xA400F0, &data, sizeof(data), sync);
  324. }
  325. /* This write will fail if there is no extension connected, that's fine */
  326. {
  327. Uint8 data = 0x00;
  328. (void)WriteRegister(ctx, 0xA400FB, &data, sizeof(data), sync);
  329. }
  330. return result;
  331. }
  332. static SDL_bool GetMotionPlusState(SDL_DriverWii_Context *ctx, SDL_bool *connected, Uint8 *mode)
  333. {
  334. Uint16 extension;
  335. if (connected) {
  336. *connected = SDL_FALSE;
  337. }
  338. if (mode) {
  339. *mode = 0;
  340. }
  341. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_WiiUPro) {
  342. /* The Wii U Pro controller never has the Motion Plus extension */
  343. return SDL_TRUE;
  344. }
  345. if (SendExtensionIdentify(ctx, SDL_TRUE) &&
  346. ParseExtensionIdentifyResponse(ctx, &extension)) {
  347. if ((extension & WII_EXTENSION_MOTIONPLUS_MASK) == WII_EXTENSION_MOTIONPLUS_ID) {
  348. /* Motion Plus is currently active */
  349. if (connected) {
  350. *connected = SDL_TRUE;
  351. }
  352. if (mode) {
  353. *mode = (extension >> 8);
  354. }
  355. return SDL_TRUE;
  356. }
  357. }
  358. if (ReadRegister(ctx, 0xA600FE, 2, SDL_TRUE) &&
  359. ParseExtensionIdentifyResponse(ctx, &extension)) {
  360. if ((extension & WII_EXTENSION_MOTIONPLUS_MASK) == WII_EXTENSION_MOTIONPLUS_ID) {
  361. /* Motion Plus is currently connected */
  362. if (connected) {
  363. *connected = SDL_TRUE;
  364. }
  365. }
  366. return SDL_TRUE;
  367. }
  368. /* Failed to read the register or parse the response */
  369. return SDL_FALSE;
  370. }
  371. static SDL_bool NeedsPeriodicMotionPlusCheck(SDL_DriverWii_Context *ctx, SDL_bool status_update)
  372. {
  373. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_WiiUPro) {
  374. /* The Wii U Pro controller never has the Motion Plus extension */
  375. return SDL_FALSE;
  376. }
  377. if (ctx->m_ucMotionPlusMode != WII_MOTIONPLUS_MODE_NONE && !status_update) {
  378. /* We'll get a status update when Motion Plus is disconnected */
  379. return SDL_FALSE;
  380. }
  381. return SDL_TRUE;
  382. }
  383. static void SchedulePeriodicMotionPlusCheck(SDL_DriverWii_Context *ctx)
  384. {
  385. ctx->m_unNextMotionPlusCheck = SDL_GetTicks() + MOTION_PLUS_UPDATE_TIME_MS;
  386. if (!ctx->m_unNextMotionPlusCheck) {
  387. ctx->m_unNextMotionPlusCheck = 1;
  388. }
  389. }
  390. static void CheckMotionPlusConnection(SDL_DriverWii_Context *ctx)
  391. {
  392. SendExtensionIdentify(ctx, SDL_FALSE);
  393. ctx->m_eCommState = k_eWiiCommunicationState_CheckMotionPlusStage1;
  394. }
  395. static void ActivateMotionPlusWithMode(SDL_DriverWii_Context *ctx, Uint8 mode)
  396. {
  397. #if defined(__LINUX__)
  398. /* Linux drivers maintain a lot of state around the Motion Plus
  399. * extension, so don't mess with it here.
  400. */
  401. #else
  402. WriteRegister(ctx, 0xA600FE, &mode, sizeof(mode), SDL_TRUE);
  403. ctx->m_ucMotionPlusMode = mode;
  404. #endif /* LINUX */
  405. }
  406. static void ActivateMotionPlus(SDL_DriverWii_Context *ctx)
  407. {
  408. Uint8 mode = WII_MOTIONPLUS_MODE_STANDARD;
  409. /* Pick the pass-through mode based on the connected controller */
  410. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_Nunchuk) {
  411. mode = WII_MOTIONPLUS_MODE_NUNCHUK;
  412. } else if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_Gamepad) {
  413. mode = WII_MOTIONPLUS_MODE_GAMEPAD;
  414. }
  415. ActivateMotionPlusWithMode(ctx, mode);
  416. }
  417. static void DeactivateMotionPlus(SDL_DriverWii_Context *ctx)
  418. {
  419. Uint8 data = 0x55;
  420. WriteRegister(ctx, 0xA400F0, &data, sizeof(data), SDL_TRUE);
  421. /* Wait for the deactivation status message */
  422. ReadInputSync(ctx, k_eWiiInputReportIDs_Status, NULL);
  423. ctx->m_ucMotionPlusMode = WII_MOTIONPLUS_MODE_NONE;
  424. }
  425. static void UpdatePowerLevelWii(SDL_Joystick *joystick, Uint8 batteryLevelByte)
  426. {
  427. if (batteryLevelByte > 178) {
  428. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
  429. } else if (batteryLevelByte > 51) {
  430. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
  431. } else if (batteryLevelByte > 13) {
  432. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
  433. } else {
  434. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
  435. }
  436. }
  437. static void UpdatePowerLevelWiiU(SDL_Joystick *joystick, Uint8 extensionBatteryByte)
  438. {
  439. SDL_bool charging = extensionBatteryByte & 0x08 ? SDL_FALSE : SDL_TRUE;
  440. SDL_bool pluggedIn = extensionBatteryByte & 0x04 ? SDL_FALSE : SDL_TRUE;
  441. Uint8 batteryLevel = extensionBatteryByte >> 4;
  442. /* Not sure if all Wii U Pro controllers act like this, but on mine
  443. * 4, 3, and 2 are held for about 20 hours each
  444. * 1 is held for about 6 hours
  445. * 0 is held for about 2 hours
  446. * No value above 4 has been observed.
  447. */
  448. if (pluggedIn && !charging) {
  449. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
  450. } else if (batteryLevel >= 4) {
  451. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
  452. } else if (batteryLevel > 1) {
  453. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
  454. } else if (batteryLevel == 1) {
  455. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
  456. } else {
  457. SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
  458. }
  459. }
  460. static EWiiInputReportIDs GetButtonPacketType(SDL_DriverWii_Context *ctx)
  461. {
  462. switch (ctx->m_eExtensionControllerType) {
  463. case k_eWiiExtensionControllerType_WiiUPro:
  464. return k_eWiiInputReportIDs_ButtonDataD;
  465. case k_eWiiExtensionControllerType_Nunchuk:
  466. case k_eWiiExtensionControllerType_Gamepad:
  467. if (ctx->m_bReportSensors) {
  468. return k_eWiiInputReportIDs_ButtonData5;
  469. } else {
  470. return k_eWiiInputReportIDs_ButtonData2;
  471. }
  472. default:
  473. if (ctx->m_bReportSensors) {
  474. return k_eWiiInputReportIDs_ButtonData5;
  475. } else {
  476. return k_eWiiInputReportIDs_ButtonData0;
  477. }
  478. }
  479. }
  480. static SDL_bool RequestButtonPacketType(SDL_DriverWii_Context *ctx, EWiiInputReportIDs type)
  481. {
  482. Uint8 data[3];
  483. Uint8 tt = ctx->m_bRumbleActive;
  484. /* Continuous reporting off, tt & 4 == 0 */
  485. if (ENABLE_CONTINUOUS_REPORTING) {
  486. tt |= 4;
  487. }
  488. data[0] = k_eWiiOutputReportIDs_DataReportingMode;
  489. data[1] = tt;
  490. data[2] = type;
  491. return WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
  492. }
  493. static void ResetButtonPacketType(SDL_DriverWii_Context *ctx)
  494. {
  495. RequestButtonPacketType(ctx, GetButtonPacketType(ctx));
  496. }
  497. static void InitStickCalibrationData(SDL_DriverWii_Context *ctx)
  498. {
  499. int i;
  500. switch (ctx->m_eExtensionControllerType) {
  501. case k_eWiiExtensionControllerType_WiiUPro:
  502. for (i = 0; i < 4; i++) {
  503. ctx->m_StickCalibrationData[i].min = 1000;
  504. ctx->m_StickCalibrationData[i].max = 3000;
  505. ctx->m_StickCalibrationData[i].center = 0;
  506. ctx->m_StickCalibrationData[i].deadzone = 100;
  507. }
  508. break;
  509. case k_eWiiExtensionControllerType_Gamepad:
  510. for (i = 0; i < 4; i++) {
  511. ctx->m_StickCalibrationData[i].min = i < 2 ? 9 : 5;
  512. ctx->m_StickCalibrationData[i].max = i < 2 ? 54 : 26;
  513. ctx->m_StickCalibrationData[i].center = 0;
  514. ctx->m_StickCalibrationData[i].deadzone = i < 2 ? 4 : 2;
  515. }
  516. break;
  517. case k_eWiiExtensionControllerType_Nunchuk:
  518. for (i = 0; i < 2; i++) {
  519. ctx->m_StickCalibrationData[i].min = 40;
  520. ctx->m_StickCalibrationData[i].max = 215;
  521. ctx->m_StickCalibrationData[i].center = 0;
  522. ctx->m_StickCalibrationData[i].deadzone = 10;
  523. }
  524. break;
  525. default:
  526. break;
  527. }
  528. }
  529. static void InitializeExtension(SDL_DriverWii_Context *ctx)
  530. {
  531. SendExtensionReset(ctx, SDL_TRUE);
  532. InitStickCalibrationData(ctx);
  533. ResetButtonPacketType(ctx);
  534. }
  535. static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  536. {
  537. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)userdata;
  538. ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
  539. }
  540. static void UpdateSlotLED(SDL_DriverWii_Context *ctx)
  541. {
  542. Uint8 leds;
  543. Uint8 data[2];
  544. /* The lowest bit needs to have the rumble status */
  545. leds = ctx->m_bRumbleActive;
  546. if (ctx->m_bPlayerLights) {
  547. /* Use the same LED codes as Smash 8-player for 5-7 */
  548. if (ctx->m_nPlayerIndex == 0 || ctx->m_nPlayerIndex > 3) {
  549. leds |= k_eWiiPlayerLEDs_P1;
  550. }
  551. if (ctx->m_nPlayerIndex == 1 || ctx->m_nPlayerIndex == 4) {
  552. leds |= k_eWiiPlayerLEDs_P2;
  553. }
  554. if (ctx->m_nPlayerIndex == 2 || ctx->m_nPlayerIndex == 5) {
  555. leds |= k_eWiiPlayerLEDs_P3;
  556. }
  557. if (ctx->m_nPlayerIndex == 3 || ctx->m_nPlayerIndex == 6) {
  558. leds |= k_eWiiPlayerLEDs_P4;
  559. }
  560. /* Turn on all lights for other player indexes */
  561. if (ctx->m_nPlayerIndex < 0 || ctx->m_nPlayerIndex > 6) {
  562. leds |= k_eWiiPlayerLEDs_P1 | k_eWiiPlayerLEDs_P2 | k_eWiiPlayerLEDs_P3 | k_eWiiPlayerLEDs_P4;
  563. }
  564. }
  565. data[0] = k_eWiiOutputReportIDs_LEDs;
  566. data[1] = leds;
  567. WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
  568. }
  569. static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  570. {
  571. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)userdata;
  572. SDL_bool bPlayerLights = SDL_GetStringBoolean(hint, SDL_TRUE);
  573. if (bPlayerLights != ctx->m_bPlayerLights) {
  574. ctx->m_bPlayerLights = bPlayerLights;
  575. UpdateSlotLED(ctx);
  576. }
  577. }
  578. static EWiiExtensionControllerType
  579. ReadExtensionControllerType(SDL_HIDAPI_Device *device)
  580. {
  581. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  582. EWiiExtensionControllerType eExtensionControllerType = k_eWiiExtensionControllerType_Unknown;
  583. const int MAX_ATTEMPTS = 20;
  584. int attempts = 0;
  585. /* Create enough of a context to read the controller type from the device */
  586. for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) {
  587. Uint16 extension;
  588. if (SendExtensionIdentify(ctx, SDL_TRUE) &&
  589. ParseExtensionIdentifyResponse(ctx, &extension)) {
  590. Uint8 motion_plus_mode = 0;
  591. if ((extension & WII_EXTENSION_MOTIONPLUS_MASK) == WII_EXTENSION_MOTIONPLUS_ID) {
  592. motion_plus_mode = (Uint8)(extension >> 8);
  593. }
  594. if (motion_plus_mode || extension == WII_EXTENSION_UNINITIALIZED) {
  595. SendExtensionReset(ctx, SDL_TRUE);
  596. if (SendExtensionIdentify(ctx, SDL_TRUE)) {
  597. ParseExtensionIdentifyResponse(ctx, &extension);
  598. }
  599. }
  600. eExtensionControllerType = GetExtensionType(extension);
  601. /* Reset the Motion Plus controller if needed */
  602. if (motion_plus_mode) {
  603. ActivateMotionPlusWithMode(ctx, motion_plus_mode);
  604. }
  605. break;
  606. }
  607. }
  608. return eExtensionControllerType;
  609. }
  610. static void
  611. UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
  612. {
  613. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  614. switch (ctx->m_eExtensionControllerType) {
  615. case k_eWiiExtensionControllerType_None:
  616. HIDAPI_SetDeviceName(device, "Nintendo Wii Remote");
  617. break;
  618. case k_eWiiExtensionControllerType_Nunchuk:
  619. HIDAPI_SetDeviceName(device, "Nintendo Wii Remote with Nunchuk");
  620. break;
  621. case k_eWiiExtensionControllerType_Gamepad:
  622. HIDAPI_SetDeviceName(device, "Nintendo Wii Remote with Classic Controller");
  623. break;
  624. case k_eWiiExtensionControllerType_WiiUPro:
  625. HIDAPI_SetDeviceName(device, "Nintendo Wii U Pro Controller");
  626. break;
  627. default:
  628. HIDAPI_SetDeviceName(device, "Nintendo Wii Remote with Unknown Extension");
  629. break;
  630. }
  631. device->guid.data[15] = ctx->m_eExtensionControllerType;
  632. }
  633. static SDL_bool
  634. HIDAPI_DriverWii_InitDevice(SDL_HIDAPI_Device *device)
  635. {
  636. SDL_DriverWii_Context *ctx;
  637. ctx = (SDL_DriverWii_Context *)SDL_calloc(1, sizeof(*ctx));
  638. if (!ctx) {
  639. SDL_OutOfMemory();
  640. return SDL_FALSE;
  641. }
  642. ctx->device = device;
  643. device->context = ctx;
  644. if (device->vendor_id == USB_VENDOR_NINTENDO) {
  645. ctx->m_eExtensionControllerType = ReadExtensionControllerType(device);
  646. UpdateDeviceIdentity(device);
  647. }
  648. return HIDAPI_JoystickConnected(device, NULL);
  649. }
  650. static int
  651. HIDAPI_DriverWii_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
  652. {
  653. return -1;
  654. }
  655. static void
  656. HIDAPI_DriverWii_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
  657. {
  658. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  659. if (!ctx->joystick) {
  660. return;
  661. }
  662. ctx->m_nPlayerIndex = player_index;
  663. UpdateSlotLED(ctx);
  664. }
  665. static SDL_bool
  666. HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  667. {
  668. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  669. ctx->joystick = joystick;
  670. InitializeExtension(ctx);
  671. GetMotionPlusState(ctx, &ctx->m_bMotionPlusPresent, &ctx->m_ucMotionPlusMode);
  672. if (NeedsPeriodicMotionPlusCheck(ctx, SDL_FALSE)) {
  673. SchedulePeriodicMotionPlusCheck(ctx);
  674. }
  675. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_None ||
  676. ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_Nunchuk) {
  677. SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f);
  678. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_Nunchuk) {
  679. SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 100.0f);
  680. }
  681. if (ctx->m_bMotionPlusPresent) {
  682. SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 100.0f);
  683. }
  684. }
  685. SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
  686. SDL_GameControllerButtonReportingHintChanged, ctx);
  687. /* Initialize player index (needed for setting LEDs) */
  688. ctx->m_nPlayerIndex = SDL_JoystickGetPlayerIndex(joystick);
  689. ctx->m_bPlayerLights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED, SDL_TRUE);
  690. UpdateSlotLED(ctx);
  691. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED,
  692. SDL_PlayerLEDHintChanged, ctx);
  693. /* Initialize the joystick capabilities */
  694. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_WiiUPro) {
  695. joystick->nbuttons = 15;
  696. } else {
  697. /* Maximum is Classic Controller + Wiimote */
  698. joystick->nbuttons = k_eWiiButtons_Max;
  699. }
  700. joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
  701. ctx->m_unLastInput = SDL_GetTicks();
  702. return SDL_TRUE;
  703. }
  704. static int
  705. HIDAPI_DriverWii_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  706. {
  707. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  708. SDL_bool active = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE;
  709. if (active != ctx->m_bRumbleActive) {
  710. Uint8 data[2];
  711. data[0] = k_eWiiOutputReportIDs_Rumble;
  712. data[1] = active;
  713. WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
  714. ctx->m_bRumbleActive = active;
  715. }
  716. return 0;
  717. }
  718. static int
  719. HIDAPI_DriverWii_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
  720. {
  721. return SDL_Unsupported();
  722. }
  723. static Uint32
  724. HIDAPI_DriverWii_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  725. {
  726. return SDL_JOYCAP_RUMBLE;
  727. }
  728. static int
  729. HIDAPI_DriverWii_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
  730. {
  731. return SDL_Unsupported();
  732. }
  733. static int
  734. HIDAPI_DriverWii_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
  735. {
  736. return SDL_Unsupported();
  737. }
  738. static int
  739. HIDAPI_DriverWii_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
  740. {
  741. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  742. if (enabled != ctx->m_bReportSensors) {
  743. ctx->m_bReportSensors = enabled;
  744. if (ctx->m_bMotionPlusPresent) {
  745. if (enabled) {
  746. ActivateMotionPlus(ctx);
  747. } else {
  748. DeactivateMotionPlus(ctx);
  749. }
  750. }
  751. ResetButtonPacketType(ctx);
  752. }
  753. return 0;
  754. }
  755. static void PostStickCalibrated(SDL_Joystick *joystick, struct StickCalibrationData *calibration, Uint8 axis, Uint16 data)
  756. {
  757. Sint16 value = 0;
  758. if (!calibration->center) {
  759. /* Center on first read */
  760. calibration->center = data;
  761. return;
  762. }
  763. if (data < calibration->min) {
  764. calibration->min = data;
  765. }
  766. if (data > calibration->max) {
  767. calibration->max = data;
  768. }
  769. if (data < calibration->center - calibration->deadzone) {
  770. Uint16 zero = calibration->center - calibration->deadzone;
  771. Uint16 range = zero - calibration->min;
  772. Uint16 distance = zero - data;
  773. float fvalue = (float)distance / (float)range;
  774. value = (Sint16)(fvalue * SDL_JOYSTICK_AXIS_MIN);
  775. } else if (data > calibration->center + calibration->deadzone) {
  776. Uint16 zero = calibration->center + calibration->deadzone;
  777. Uint16 range = calibration->max - zero;
  778. Uint16 distance = data - zero;
  779. float fvalue = (float)distance / (float)range;
  780. value = (Sint16)(fvalue * SDL_JOYSTICK_AXIS_MAX);
  781. }
  782. if (axis == SDL_CONTROLLER_AXIS_LEFTY || axis == SDL_CONTROLLER_AXIS_RIGHTY) {
  783. if (value) {
  784. value = ~value;
  785. }
  786. }
  787. SDL_PrivateJoystickAxis(joystick, axis, value);
  788. }
  789. /* Send button data to SDL
  790. *`defs` is a mapping for each bit to which button it represents. 0xFF indicates an unused bit
  791. *`data` is the button data from the controller
  792. *`size` is the number of bytes in `data` and the number of arrays of 8 mappings in `defs`
  793. *`on` is the joystick value to be sent if a bit is on
  794. *`off` is the joystick value to be sent if a bit is off
  795. */
  796. static void PostPackedButtonData(SDL_Joystick *joystick, const Uint8 defs[][8], const Uint8* data, int size, Uint8 on, Uint8 off)
  797. {
  798. int i, j;
  799. for (i = 0; i < size; i++) {
  800. for (j = 0; j < 8; j++) {
  801. Uint8 button = defs[i][j];
  802. if (button != 0xFF) {
  803. Uint8 state = (data[i] >> j) & 1 ? on : off;
  804. SDL_PrivateJoystickButton(joystick, button, state);
  805. }
  806. }
  807. }
  808. }
  809. static const Uint8 GAMEPAD_BUTTON_DEFS[3][8] = {
  810. {
  811. 0xFF /* Unused */, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_GUIDE,
  812. SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_DPAD_DOWN, SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
  813. }, {
  814. SDL_CONTROLLER_BUTTON_DPAD_UP, SDL_CONTROLLER_BUTTON_DPAD_LEFT, 0xFF /* ZR */, SDL_CONTROLLER_BUTTON_X,
  815. SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_B, 0xFF /*ZL*/,
  816. }, {
  817. SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_LEFTSTICK, 0xFF /* Charging */, 0xFF /* Plugged In */,
  818. 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */,
  819. }
  820. };
  821. static const Uint8 GAMEPAD_BUTTON_DEFS_POSITIONAL[3][8] = {
  822. {
  823. 0xFF /* Unused */, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_GUIDE,
  824. SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_DPAD_DOWN, SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
  825. }, {
  826. SDL_CONTROLLER_BUTTON_DPAD_UP, SDL_CONTROLLER_BUTTON_DPAD_LEFT, 0xFF /* ZR */, SDL_CONTROLLER_BUTTON_Y,
  827. SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_A, 0xFF /*ZL*/,
  828. }, {
  829. SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_LEFTSTICK, 0xFF /* Charging */, 0xFF /* Plugged In */,
  830. 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */,
  831. }
  832. };
  833. static const Uint8 MP_GAMEPAD_BUTTON_DEFS[3][8] = {
  834. {
  835. 0xFF /* Unused */, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_GUIDE,
  836. SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_DPAD_DOWN, SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
  837. }, {
  838. 0xFF /* Motion Plus data */, 0xFF /* Motion Plus data */, 0xFF /* ZR */, SDL_CONTROLLER_BUTTON_X,
  839. SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_B, 0xFF /*ZL*/,
  840. }, {
  841. SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_LEFTSTICK, 0xFF /* Charging */, 0xFF /* Plugged In */,
  842. 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */,
  843. }
  844. };
  845. static const Uint8 MP_GAMEPAD_BUTTON_DEFS_POSITIONAL[3][8] = {
  846. {
  847. 0xFF /* Unused */, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_GUIDE,
  848. SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_DPAD_DOWN, SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
  849. }, {
  850. 0xFF /* Motion Plus data */, 0xFF /* Motion Plus data */, 0xFF /* ZR */, SDL_CONTROLLER_BUTTON_Y,
  851. SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_A, 0xFF /*ZL*/,
  852. }, {
  853. SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_LEFTSTICK, 0xFF /* Charging */, 0xFF /* Plugged In */,
  854. 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */,
  855. }
  856. };
  857. static const Uint8 MP_FIXUP_DPAD_BUTTON_DEFS[2][8] = {
  858. {
  859. SDL_CONTROLLER_BUTTON_DPAD_UP, 0xFF, 0xFF, 0xFF,
  860. 0xFF, 0xFF, 0xFF, 0xFF,
  861. }, {
  862. SDL_CONTROLLER_BUTTON_DPAD_LEFT, 0xFF, 0xFF, 0xFF,
  863. 0xFF, 0xFF, 0xFF, 0xFF,
  864. }
  865. };
  866. static void HandleWiiUProButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
  867. {
  868. static const Uint8 axes[] = { SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_LEFTY, SDL_CONTROLLER_AXIS_RIGHTY };
  869. const Uint8 (*buttons)[8] = ctx->m_bUseButtonLabels ? GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS_POSITIONAL;
  870. Uint8 zl, zr;
  871. int i;
  872. if (data->ucNExtensionBytes < 11) {
  873. return;
  874. }
  875. /* Buttons */
  876. PostPackedButtonData(joystick, buttons, data->rgucExtension + 8, 3, SDL_RELEASED, SDL_PRESSED);
  877. /* Triggers */
  878. zl = data->rgucExtension[9] & 0x80;
  879. zr = data->rgucExtension[9] & 0x04;
  880. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, zl ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX);
  881. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, zr ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX);
  882. /* Sticks */
  883. for (i = 0; i < 4; i++) {
  884. Uint16 value = data->rgucExtension[i * 2] | (data->rgucExtension[i * 2 + 1] << 8);
  885. PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[i], axes[i], value);
  886. }
  887. /* Power */
  888. UpdatePowerLevelWiiU(joystick, data->rgucExtension[10]);
  889. }
  890. static void HandleGamepadControllerButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
  891. {
  892. const Uint8 (*buttons)[8] = ctx->m_bUseButtonLabels ?
  893. ((ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS) :
  894. ((ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS_POSITIONAL : GAMEPAD_BUTTON_DEFS_POSITIONAL);
  895. Uint8 lx, ly, rx, ry, zl, zr;
  896. if (data->ucNExtensionBytes < 6) {
  897. return;
  898. }
  899. /* Buttons */
  900. PostPackedButtonData(joystick, buttons, data->rgucExtension + 4, 2, SDL_RELEASED, SDL_PRESSED);
  901. if (ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) {
  902. PostPackedButtonData(joystick, MP_FIXUP_DPAD_BUTTON_DEFS, data->rgucExtension, 2, SDL_RELEASED, SDL_PRESSED);
  903. }
  904. /* Triggers */
  905. zl = data->rgucExtension[5] & 0x80;
  906. zr = data->rgucExtension[5] & 0x04;
  907. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, zl ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX);
  908. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, zr ? SDL_JOYSTICK_AXIS_MIN : SDL_JOYSTICK_AXIS_MAX);
  909. /* Sticks */
  910. if (ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) {
  911. lx = data->rgucExtension[0] & 0x3E;
  912. ly = data->rgucExtension[1] & 0x3E;
  913. } else {
  914. lx = data->rgucExtension[0] & 0x3F;
  915. ly = data->rgucExtension[1] & 0x3F;
  916. }
  917. rx = (data->rgucExtension[2] >> 7) | ((data->rgucExtension[1] >> 5) & 0x06) | ((data->rgucExtension[0] >> 3) & 0x18);
  918. ry = data->rgucExtension[2] & 0x1F;
  919. PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[0], SDL_CONTROLLER_AXIS_LEFTX, lx);
  920. PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[1], SDL_CONTROLLER_AXIS_LEFTY, ly);
  921. PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[2], SDL_CONTROLLER_AXIS_RIGHTX, rx);
  922. PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[3], SDL_CONTROLLER_AXIS_RIGHTY, ry);
  923. }
  924. static void HandleWiiRemoteButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
  925. {
  926. static const Uint8 buttons[2][8] = {
  927. {
  928. k_eWiiButtons_DPad_Left, k_eWiiButtons_DPad_Right, k_eWiiButtons_DPad_Down, k_eWiiButtons_DPad_Up,
  929. k_eWiiButtons_Plus, 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */,
  930. }, {
  931. k_eWiiButtons_Two, k_eWiiButtons_One, k_eWiiButtons_B, k_eWiiButtons_A,
  932. k_eWiiButtons_Minus, 0xFF /* Unused */, 0xFF /* Unused */, k_eWiiButtons_Home,
  933. }
  934. };
  935. if (data->hasBaseButtons) {
  936. PostPackedButtonData(joystick, buttons, data->rgucBaseButtons, 2, SDL_PRESSED, SDL_RELEASED);
  937. }
  938. }
  939. static void HandleWiiRemoteButtonDataAsMainController(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
  940. {
  941. /* Wii remote maps really badly to a normal controller
  942. * Mapped 1 and 2 as X and Y
  943. * Not going to attempt positional mapping
  944. */
  945. static const Uint8 buttons[2][8] = {
  946. {
  947. SDL_CONTROLLER_BUTTON_DPAD_LEFT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_DOWN, SDL_CONTROLLER_BUTTON_DPAD_UP,
  948. SDL_CONTROLLER_BUTTON_START, 0xFF /* Unused */, 0xFF /* Unused */, 0xFF /* Unused */,
  949. }, {
  950. SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_B,
  951. SDL_CONTROLLER_BUTTON_BACK, 0xFF /* Unused */, 0xFF /* Unused */, SDL_CONTROLLER_BUTTON_GUIDE,
  952. }
  953. };
  954. if (data->hasBaseButtons) {
  955. PostPackedButtonData(joystick, buttons, data->rgucBaseButtons, 2, SDL_PRESSED, SDL_RELEASED);
  956. }
  957. }
  958. static void HandleNunchuckButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
  959. {
  960. Uint8 c, z;
  961. if (data->ucNExtensionBytes < 6) {
  962. return;
  963. }
  964. if (ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_NUNCHUK) {
  965. c = (data->rgucExtension[5] & 0x08) ? SDL_RELEASED : SDL_PRESSED;
  966. z = (data->rgucExtension[5] & 0x04) ? SDL_RELEASED : SDL_PRESSED;
  967. } else {
  968. c = (data->rgucExtension[5] & 0x02) ? SDL_RELEASED : SDL_PRESSED;
  969. z = (data->rgucExtension[5] & 0x01) ? SDL_RELEASED : SDL_PRESSED;
  970. }
  971. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, c);
  972. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, z ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN);
  973. PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[0], SDL_CONTROLLER_AXIS_LEFTX, data->rgucExtension[0]);
  974. PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[1], SDL_CONTROLLER_AXIS_LEFTY, data->rgucExtension[1]);
  975. if (ctx->m_bReportSensors) {
  976. const float ACCEL_RES_PER_G = 200.0f;
  977. Sint16 x, y, z;
  978. float values[3];
  979. x = (data->rgucExtension[2] << 2);
  980. y = (data->rgucExtension[3] << 2);
  981. z = (data->rgucExtension[4] << 2);
  982. if (ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_NUNCHUK) {
  983. x |= ((data->rgucExtension[5] >> 3) & 0x02);
  984. y |= ((data->rgucExtension[5] >> 4) & 0x02);
  985. z &= ~0x04;
  986. z |= ((data->rgucExtension[5] >> 5) & 0x06);
  987. } else {
  988. x |= ((data->rgucExtension[5] >> 2) & 0x03);
  989. y |= ((data->rgucExtension[5] >> 4) & 0x03);
  990. z |= ((data->rgucExtension[5] >> 6) & 0x03);
  991. }
  992. x -= 0x200;
  993. y -= 0x200;
  994. z -= 0x200;
  995. values[0] = -((float)x / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
  996. values[1] = ((float)z / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
  997. values[2] = ((float)y / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
  998. SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL_L, values, 3);
  999. }
  1000. }
  1001. static void HandleMotionPlusData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
  1002. {
  1003. if (ctx->m_bReportSensors) {
  1004. const float GYRO_RES_PER_DEGREE = 8192.0f;
  1005. int x, y, z;
  1006. float values[3];
  1007. x = (data->rgucExtension[0] | ((data->rgucExtension[3] << 6) & 0xFF00)) - 8192;
  1008. y = (data->rgucExtension[1] | ((data->rgucExtension[4] << 6) & 0xFF00)) - 8192;
  1009. z = (data->rgucExtension[2] | ((data->rgucExtension[5] << 6) & 0xFF00)) - 8192;
  1010. if (data->rgucExtension[3] & 0x02) {
  1011. /* Slow rotation rate: 8192/440 units per deg/s */
  1012. x *= 440;
  1013. } else {
  1014. /* Fast rotation rate: 8192/2000 units per deg/s */
  1015. x *= 2000;
  1016. }
  1017. if (data->rgucExtension[4] & 0x02) {
  1018. /* Slow rotation rate: 8192/440 units per deg/s */
  1019. y *= 440;
  1020. } else {
  1021. /* Fast rotation rate: 8192/2000 units per deg/s */
  1022. y *= 2000;
  1023. }
  1024. if (data->rgucExtension[3] & 0x01) {
  1025. /* Slow rotation rate: 8192/440 units per deg/s */
  1026. z *= 440;
  1027. } else {
  1028. /* Fast rotation rate: 8192/2000 units per deg/s */
  1029. z *= 2000;
  1030. }
  1031. values[0] = -((float)z / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f;
  1032. values[1] = ((float)x / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f;
  1033. values[2] = ((float)y / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f;
  1034. SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, values, 3);
  1035. }
  1036. }
  1037. static void HandleWiiRemoteAccelData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
  1038. {
  1039. const float ACCEL_RES_PER_G = 100.0f;
  1040. Sint16 x, y, z;
  1041. float values[3];
  1042. if (!ctx->m_bReportSensors) {
  1043. return;
  1044. }
  1045. x = ((data->rgucAccelerometer[0] << 2) | ((data->rgucBaseButtons[0] >> 5) & 0x03)) - 0x200;
  1046. y = ((data->rgucAccelerometer[1] << 2) | ((data->rgucBaseButtons[1] >> 4) & 0x02)) - 0x200;
  1047. z = ((data->rgucAccelerometer[2] << 2) | ((data->rgucBaseButtons[1] >> 5) & 0x02)) - 0x200;
  1048. values[0] = -((float)x / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
  1049. values[1] = ((float)z / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
  1050. values[2] = ((float)y / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
  1051. SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, values, 3);
  1052. }
  1053. static void HandleButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, WiiButtonData *data)
  1054. {
  1055. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_WiiUPro) {
  1056. HandleWiiUProButtonData(ctx, joystick, data);
  1057. return;
  1058. }
  1059. if (ctx->m_ucMotionPlusMode != WII_MOTIONPLUS_MODE_NONE &&
  1060. data->ucNExtensionBytes > 5) {
  1061. if (data->rgucExtension[5] & 0x01) {
  1062. /* The data is invalid, possibly during a hotplug */
  1063. return;
  1064. }
  1065. if (data->rgucExtension[4] & 0x01) {
  1066. if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_None) {
  1067. /* Something was plugged into the extension port, reinitialize to get new state */
  1068. ctx->m_bDisconnected = SDL_TRUE;
  1069. }
  1070. } else {
  1071. if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_None) {
  1072. /* Something was removed from the extension port, reinitialize to get new state */
  1073. ctx->m_bDisconnected = SDL_TRUE;
  1074. }
  1075. }
  1076. if (data->rgucExtension[5] & 0x02) {
  1077. HandleMotionPlusData(ctx, joystick, data);
  1078. /* The extension data is consumed */
  1079. data->ucNExtensionBytes = 0;
  1080. }
  1081. }
  1082. HandleWiiRemoteButtonData(ctx, joystick, data);
  1083. switch (ctx->m_eExtensionControllerType) {
  1084. case k_eWiiExtensionControllerType_Nunchuk:
  1085. HandleNunchuckButtonData(ctx, joystick, data);
  1086. SDL_FALLTHROUGH;
  1087. case k_eWiiExtensionControllerType_None:
  1088. HandleWiiRemoteButtonDataAsMainController(ctx, joystick, data);
  1089. break;
  1090. case k_eWiiExtensionControllerType_Gamepad:
  1091. HandleGamepadControllerButtonData(ctx, joystick, data);
  1092. break;
  1093. default:
  1094. break;
  1095. }
  1096. HandleWiiRemoteAccelData(ctx, joystick, data);
  1097. }
  1098. static void GetBaseButtons(WiiButtonData *dst, const Uint8 *src)
  1099. {
  1100. SDL_memcpy(dst->rgucBaseButtons, src, 2);
  1101. dst->hasBaseButtons = SDL_TRUE;
  1102. }
  1103. static void GetAccelerometer(WiiButtonData *dst, const Uint8 *src)
  1104. {
  1105. SDL_memcpy(dst->rgucAccelerometer, src, 3);
  1106. dst->hasAccelerometer = SDL_TRUE;
  1107. }
  1108. static void GetExtensionData(WiiButtonData *dst, const Uint8 *src, int size)
  1109. {
  1110. SDL_bool valid_data = SDL_FALSE;
  1111. int i;
  1112. if (size > sizeof(dst->rgucExtension)) {
  1113. size = sizeof(dst->rgucExtension);
  1114. }
  1115. for (i = 0; i < size; ++i) {
  1116. if (src[i] != 0xFF) {
  1117. valid_data = SDL_TRUE;
  1118. break;
  1119. }
  1120. }
  1121. if (valid_data) {
  1122. SDL_memcpy(dst->rgucExtension, src, size);
  1123. dst->ucNExtensionBytes = size;
  1124. }
  1125. }
  1126. static void HandleStatus(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick)
  1127. {
  1128. SDL_bool hadExtension = ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_None;
  1129. SDL_bool hasExtension = ctx->m_rgucReadBuffer[3] & 2 ? SDL_TRUE : SDL_FALSE;
  1130. WiiButtonData data;
  1131. SDL_zero(data);
  1132. GetBaseButtons(&data, ctx->m_rgucReadBuffer + 1);
  1133. HandleButtonData(ctx, joystick, &data);
  1134. if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_WiiUPro) {
  1135. /* Wii U has separate battery level tracking */
  1136. UpdatePowerLevelWii(joystick, ctx->m_rgucReadBuffer[6]);
  1137. }
  1138. /* The report data format has been reset, need to update it */
  1139. ResetButtonPacketType(ctx);
  1140. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "HIDAPI Wii: Status update, extension %s\n", hasExtension ? "CONNECTED" : "DISCONNECTED");
  1141. /* When Motion Plus is active, we get extension connect/disconnect status
  1142. * through the Motion Plus packets. Otherwise we can use the status here.
  1143. */
  1144. if (ctx->m_ucMotionPlusMode != WII_MOTIONPLUS_MODE_NONE) {
  1145. /* Check to make sure the Motion Plus extension state hasn't changed,
  1146. * otherwise we'll get extension connect/disconnect status through
  1147. * Motion Plus packets.
  1148. */
  1149. if (NeedsPeriodicMotionPlusCheck(ctx, SDL_TRUE)) {
  1150. ctx->m_unNextMotionPlusCheck = SDL_GetTicks();
  1151. }
  1152. } else if (hadExtension != hasExtension) {
  1153. /* Reinitialize to get new state */
  1154. ctx->m_bDisconnected = SDL_TRUE;
  1155. }
  1156. }
  1157. static void HandleResponse(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick)
  1158. {
  1159. EWiiInputReportIDs type = ctx->m_rgucReadBuffer[0];
  1160. WiiButtonData data;
  1161. SDL_assert(type == k_eWiiInputReportIDs_Acknowledge || type == k_eWiiInputReportIDs_ReadMemory);
  1162. SDL_zero(data);
  1163. GetBaseButtons(&data, ctx->m_rgucReadBuffer + 1);
  1164. HandleButtonData(ctx, joystick, &data);
  1165. switch (ctx->m_eCommState) {
  1166. case k_eWiiCommunicationState_None:
  1167. break;
  1168. case k_eWiiCommunicationState_CheckMotionPlusStage1:
  1169. case k_eWiiCommunicationState_CheckMotionPlusStage2:
  1170. {
  1171. Uint16 extension = 0;
  1172. if (ParseExtensionIdentifyResponse(ctx, &extension)) {
  1173. if ((extension & WII_EXTENSION_MOTIONPLUS_MASK) == WII_EXTENSION_MOTIONPLUS_ID) {
  1174. /* Motion Plus is currently active */
  1175. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "HIDAPI Wii: Motion Plus CONNECTED (stage %d)\n", ctx->m_eCommState == k_eWiiCommunicationState_CheckMotionPlusStage1 ? 1 : 2);
  1176. if (!ctx->m_bMotionPlusPresent) {
  1177. /* Reinitialize to get new sensor availability */
  1178. ctx->m_bDisconnected = SDL_TRUE;
  1179. }
  1180. ctx->m_eCommState = k_eWiiCommunicationState_None;
  1181. } else if (ctx->m_eCommState == k_eWiiCommunicationState_CheckMotionPlusStage1) {
  1182. /* Check to see if Motion Plus is present */
  1183. ReadRegister(ctx, 0xA600FE, 2, SDL_FALSE);
  1184. ctx->m_eCommState = k_eWiiCommunicationState_CheckMotionPlusStage2;
  1185. } else {
  1186. /* Motion Plus is not present */
  1187. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "HIDAPI Wii: Motion Plus DISCONNECTED (stage %d)\n", ctx->m_eCommState == k_eWiiCommunicationState_CheckMotionPlusStage1 ? 1 : 2);
  1188. if (ctx->m_bMotionPlusPresent) {
  1189. /* Reinitialize to get new sensor availability */
  1190. ctx->m_bDisconnected = SDL_TRUE;
  1191. }
  1192. ctx->m_eCommState = k_eWiiCommunicationState_None;
  1193. }
  1194. }
  1195. }
  1196. break;
  1197. default:
  1198. /* Should never happen */
  1199. break;
  1200. }
  1201. }
  1202. static void HandleButtonPacket(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick)
  1203. {
  1204. EWiiInputReportIDs eExpectedReport = GetButtonPacketType(ctx);
  1205. WiiButtonData data;
  1206. /* FIXME: This should see if the data format is compatible rather than equal */
  1207. if (eExpectedReport != ctx->m_rgucReadBuffer[0]) {
  1208. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "HIDAPI Wii: Resetting report mode to %d\n", eExpectedReport);
  1209. RequestButtonPacketType(ctx, eExpectedReport);
  1210. }
  1211. /* IR camera data is not supported */
  1212. SDL_zero(data);
  1213. switch (ctx->m_rgucReadBuffer[0]) {
  1214. case k_eWiiInputReportIDs_ButtonData0: /* 30 BB BB */
  1215. GetBaseButtons(&data, ctx->m_rgucReadBuffer + 1);
  1216. break;
  1217. case k_eWiiInputReportIDs_ButtonData1: /* 31 BB BB AA AA AA */
  1218. case k_eWiiInputReportIDs_ButtonData3: /* 33 BB BB AA AA AA II II II II II II II II II II II II */
  1219. GetBaseButtons (&data, ctx->m_rgucReadBuffer + 1);
  1220. GetAccelerometer(&data, ctx->m_rgucReadBuffer + 3);
  1221. break;
  1222. case k_eWiiInputReportIDs_ButtonData2: /* 32 BB BB EE EE EE EE EE EE EE EE */
  1223. GetBaseButtons (&data, ctx->m_rgucReadBuffer + 1);
  1224. GetExtensionData(&data, ctx->m_rgucReadBuffer + 3, 8);
  1225. break;
  1226. case k_eWiiInputReportIDs_ButtonData4: /* 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE */
  1227. GetBaseButtons (&data, ctx->m_rgucReadBuffer + 1);
  1228. GetExtensionData(&data, ctx->m_rgucReadBuffer + 3, 19);
  1229. break;
  1230. case k_eWiiInputReportIDs_ButtonData5: /* 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE */
  1231. GetBaseButtons (&data, ctx->m_rgucReadBuffer + 1);
  1232. GetAccelerometer(&data, ctx->m_rgucReadBuffer + 3);
  1233. GetExtensionData(&data, ctx->m_rgucReadBuffer + 6, 16);
  1234. break;
  1235. case k_eWiiInputReportIDs_ButtonData6: /* 36 BB BB II II II II II II II II II II EE EE EE EE EE EE EE EE EE */
  1236. GetBaseButtons (&data, ctx->m_rgucReadBuffer + 1);
  1237. GetExtensionData(&data, ctx->m_rgucReadBuffer + 13, 9);
  1238. break;
  1239. case k_eWiiInputReportIDs_ButtonData7: /* 37 BB BB AA AA AA II II II II II II II II II II EE EE EE EE EE EE */
  1240. GetBaseButtons (&data, ctx->m_rgucReadBuffer + 1);
  1241. GetExtensionData(&data, ctx->m_rgucReadBuffer + 16, 6);
  1242. break;
  1243. case k_eWiiInputReportIDs_ButtonDataD: /* 3d EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE */
  1244. GetExtensionData(&data, ctx->m_rgucReadBuffer + 1, 21);
  1245. break;
  1246. case k_eWiiInputReportIDs_ButtonDataE:
  1247. case k_eWiiInputReportIDs_ButtonDataF:
  1248. default:
  1249. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "HIDAPI Wii: Unsupported button data type %02x", ctx->m_rgucReadBuffer[0]);
  1250. return;
  1251. }
  1252. HandleButtonData(ctx, joystick, &data);
  1253. }
  1254. static void HandleInput(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick)
  1255. {
  1256. EWiiInputReportIDs type = ctx->m_rgucReadBuffer[0];
  1257. if (type == k_eWiiInputReportIDs_Status) {
  1258. HandleStatus(ctx, joystick);
  1259. } else if (type == k_eWiiInputReportIDs_Acknowledge || type == k_eWiiInputReportIDs_ReadMemory) {
  1260. HandleResponse(ctx, joystick);
  1261. } else if (type >= k_eWiiInputReportIDs_ButtonData0 && type <= k_eWiiInputReportIDs_ButtonDataF) {
  1262. HandleButtonPacket(ctx, joystick);
  1263. } else {
  1264. SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "HIDAPI Wii: Unexpected input packet of type %x", type);
  1265. }
  1266. }
  1267. static SDL_bool
  1268. HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
  1269. {
  1270. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  1271. SDL_Joystick *joystick = NULL;
  1272. int size;
  1273. Uint32 now;
  1274. if (device->num_joysticks > 0) {
  1275. joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
  1276. } else {
  1277. return SDL_FALSE;
  1278. }
  1279. now = SDL_GetTicks();
  1280. while ((size = ReadInput(ctx)) > 0) {
  1281. if (joystick) {
  1282. HandleInput(ctx, joystick);
  1283. }
  1284. ctx->m_unLastInput = now;
  1285. }
  1286. /* Check to see if we've lost connection to the controller.
  1287. * We have continuous reporting enabled, so this should be reliable now.
  1288. */
  1289. {
  1290. SDL_COMPILE_TIME_ASSERT(ENABLE_CONTINUOUS_REPORTING, ENABLE_CONTINUOUS_REPORTING);
  1291. }
  1292. if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) {
  1293. /* Bluetooth may have disconnected, try reopening the controller */
  1294. size = -1;
  1295. }
  1296. if (joystick) {
  1297. /* These checks aren't needed on the Wii U Pro Controller */
  1298. if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_WiiUPro) {
  1299. /* Check to see if the Motion Plus extension status has changed */
  1300. if (ctx->m_unNextMotionPlusCheck &&
  1301. SDL_TICKS_PASSED(now, ctx->m_unNextMotionPlusCheck)) {
  1302. CheckMotionPlusConnection(ctx);
  1303. if (NeedsPeriodicMotionPlusCheck(ctx, SDL_FALSE)) {
  1304. SchedulePeriodicMotionPlusCheck(ctx);
  1305. } else {
  1306. ctx->m_unNextMotionPlusCheck = 0;
  1307. }
  1308. }
  1309. /* Request a status update periodically to make sure our battery value is up to date */
  1310. if (!ctx->m_unLastStatus ||
  1311. SDL_TICKS_PASSED(now, ctx->m_unLastStatus + STATUS_UPDATE_TIME_MS)) {
  1312. Uint8 data[2];
  1313. data[0] = k_eWiiOutputReportIDs_StatusRequest;
  1314. data[1] = ctx->m_bRumbleActive;
  1315. WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
  1316. ctx->m_unLastStatus = now;
  1317. }
  1318. }
  1319. }
  1320. if (size < 0 || ctx->m_bDisconnected) {
  1321. /* Read error, device is disconnected */
  1322. HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
  1323. }
  1324. return (size >= 0);
  1325. }
  1326. static void
  1327. HIDAPI_DriverWii_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  1328. {
  1329. SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
  1330. SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
  1331. SDL_GameControllerButtonReportingHintChanged, ctx);
  1332. SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED,
  1333. SDL_PlayerLEDHintChanged, ctx);
  1334. ctx->joystick = NULL;
  1335. }
  1336. static void
  1337. HIDAPI_DriverWii_FreeDevice(SDL_HIDAPI_Device *device)
  1338. {
  1339. }
  1340. SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverWii =
  1341. {
  1342. SDL_HINT_JOYSTICK_HIDAPI_WII,
  1343. SDL_TRUE,
  1344. HIDAPI_DriverWii_RegisterHints,
  1345. HIDAPI_DriverWii_UnregisterHints,
  1346. HIDAPI_DriverWii_IsEnabled,
  1347. HIDAPI_DriverWii_IsSupportedDevice,
  1348. HIDAPI_DriverWii_InitDevice,
  1349. HIDAPI_DriverWii_GetDevicePlayerIndex,
  1350. HIDAPI_DriverWii_SetDevicePlayerIndex,
  1351. HIDAPI_DriverWii_UpdateDevice,
  1352. HIDAPI_DriverWii_OpenJoystick,
  1353. HIDAPI_DriverWii_RumbleJoystick,
  1354. HIDAPI_DriverWii_RumbleJoystickTriggers,
  1355. HIDAPI_DriverWii_GetJoystickCapabilities,
  1356. HIDAPI_DriverWii_SetJoystickLED,
  1357. HIDAPI_DriverWii_SendJoystickEffect,
  1358. HIDAPI_DriverWii_SetJoystickSensorsEnabled,
  1359. HIDAPI_DriverWii_CloseJoystick,
  1360. HIDAPI_DriverWii_FreeDevice,
  1361. };
  1362. #endif /* SDL_JOYSTICK_HIDAPI_WII */
  1363. #endif /* SDL_JOYSTICK_HIDAPI */
  1364. /* vi: set ts=4 sw=4 expandtab: */