SDL_hidapi_switch.c 127 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2026 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. /* This driver supports the Nintendo Switch Pro controller.
  19. Code and logic contributed by Valve Corporation under the SDL zlib license.
  20. */
  21. #include "SDL_internal.h"
  22. #ifdef SDL_JOYSTICK_HIDAPI
  23. #include "../../SDL_hints_c.h"
  24. #include "../SDL_sysjoystick.h"
  25. #include "SDL_hidapijoystick_c.h"
  26. #include "SDL_hidapi_rumble.h"
  27. #include "SDL_hidapi_nintendo.h"
  28. #ifdef SDL_JOYSTICK_HIDAPI_SWITCH
  29. // Define this if you want to log all packets from the controller
  30. #if 0
  31. #define DEBUG_SWITCH_PROTOCOL
  32. #endif
  33. // Define this to get log output for rumble logic
  34. // #define DEBUG_RUMBLE
  35. /* The initialization sequence doesn't appear to work correctly on Windows unless
  36. the reads and writes are on the same thread.
  37. ... and now I can't reproduce this, so I'm leaving it in, but disabled for now.
  38. */
  39. // #define SWITCH_SYNCHRONOUS_WRITES
  40. /* How often you can write rumble commands to the controller.
  41. If you send commands more frequently than this, you can turn off the controller
  42. in Bluetooth mode, or the motors can miss the command in USB mode.
  43. */
  44. #define RUMBLE_WRITE_FREQUENCY_MS 30
  45. // How often you have to refresh a long duration rumble to keep the motors running
  46. #define RUMBLE_REFRESH_FREQUENCY_MS 50
  47. #define SWITCH_GYRO_SCALE 14.2842f
  48. #define SWITCH_ACCEL_SCALE 4096.f
  49. #define SWITCH_GYRO_SCALE_MULT 936.0f
  50. #define SWITCH_ACCEL_SCALE_MULT 4.0f
  51. enum
  52. {
  53. SDL_GAMEPAD_BUTTON_SWITCH_SHARE = 11,
  54. SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1,
  55. SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1,
  56. SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2,
  57. SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2,
  58. SDL_GAMEPAD_NUM_SWITCH_BUTTONS,
  59. };
  60. typedef enum
  61. {
  62. k_eSwitchInputReportIDs_SubcommandReply = 0x21,
  63. k_eSwitchInputReportIDs_FullControllerState = 0x30,
  64. k_eSwitchInputReportIDs_FullControllerAndMcuState = 0x31,
  65. k_eSwitchInputReportIDs_SimpleControllerState = 0x3F,
  66. k_eSwitchInputReportIDs_CommandAck = 0x81,
  67. } ESwitchInputReportIDs;
  68. typedef enum
  69. {
  70. k_eSwitchOutputReportIDs_RumbleAndSubcommand = 0x01,
  71. k_eSwitchOutputReportIDs_Rumble = 0x10,
  72. k_eSwitchOutputReportIDs_Proprietary = 0x80,
  73. } ESwitchOutputReportIDs;
  74. typedef enum
  75. {
  76. k_eSwitchSubcommandIDs_BluetoothManualPair = 0x01,
  77. k_eSwitchSubcommandIDs_RequestDeviceInfo = 0x02,
  78. k_eSwitchSubcommandIDs_SetInputReportMode = 0x03,
  79. k_eSwitchSubcommandIDs_SetHCIState = 0x06,
  80. k_eSwitchSubcommandIDs_SPIFlashRead = 0x10,
  81. k_eSwitchSubcommandIDs_SetPlayerLights = 0x30,
  82. k_eSwitchSubcommandIDs_SetHomeLight = 0x38,
  83. k_eSwitchSubcommandIDs_EnableIMU = 0x40,
  84. k_eSwitchSubcommandIDs_SetIMUSensitivity = 0x41,
  85. k_eSwitchSubcommandIDs_EnableVibration = 0x48,
  86. } ESwitchSubcommandIDs;
  87. typedef enum
  88. {
  89. k_eSwitchProprietaryCommandIDs_Status = 0x01,
  90. k_eSwitchProprietaryCommandIDs_Handshake = 0x02,
  91. k_eSwitchProprietaryCommandIDs_HighSpeed = 0x03,
  92. k_eSwitchProprietaryCommandIDs_ForceUSB = 0x04,
  93. k_eSwitchProprietaryCommandIDs_ClearUSB = 0x05,
  94. k_eSwitchProprietaryCommandIDs_ResetMCU = 0x06,
  95. } ESwitchProprietaryCommandIDs;
  96. #define k_unSwitchOutputPacketDataLength 49
  97. #define k_unSwitchMaxOutputPacketLength 64
  98. #define k_unSwitchBluetoothPacketLength k_unSwitchOutputPacketDataLength
  99. #define k_unSwitchUSBPacketLength k_unSwitchMaxOutputPacketLength
  100. #define k_unSPIStickFactoryCalibrationStartOffset 0x603D
  101. #define k_unSPIStickFactoryCalibrationEndOffset 0x604E
  102. #define k_unSPIStickFactoryCalibrationLength (k_unSPIStickFactoryCalibrationEndOffset - k_unSPIStickFactoryCalibrationStartOffset + 1)
  103. #define k_unSPIStickUserCalibrationStartOffset 0x8010
  104. #define k_unSPIStickUserCalibrationEndOffset 0x8025
  105. #define k_unSPIStickUserCalibrationLength (k_unSPIStickUserCalibrationEndOffset - k_unSPIStickUserCalibrationStartOffset + 1)
  106. #define k_unSPIIMUScaleStartOffset 0x6020
  107. #define k_unSPIIMUScaleEndOffset 0x6037
  108. #define k_unSPIIMUScaleLength (k_unSPIIMUScaleEndOffset - k_unSPIIMUScaleStartOffset + 1)
  109. #define k_unSPIIMUUserScaleStartOffset 0x8026
  110. #define k_unSPIIMUUserScaleEndOffset 0x8039
  111. #define k_unSPIIMUUserScaleLength (k_unSPIIMUUserScaleEndOffset - k_unSPIIMUUserScaleStartOffset + 1)
  112. #pragma pack(1)
  113. typedef struct
  114. {
  115. Uint8 rgucButtons[2];
  116. Uint8 ucStickHat;
  117. Uint8 rgucJoystickLeft[2];
  118. Uint8 rgucJoystickRight[2];
  119. } SwitchInputOnlyControllerStatePacket_t;
  120. typedef struct
  121. {
  122. Uint8 rgucButtons[2];
  123. Uint8 ucStickHat;
  124. Sint16 sJoystickLeft[2];
  125. Sint16 sJoystickRight[2];
  126. } SwitchSimpleStatePacket_t;
  127. typedef struct
  128. {
  129. Uint8 ucCounter;
  130. Uint8 ucBatteryAndConnection;
  131. Uint8 rgucButtons[3];
  132. Uint8 rgucJoystickLeft[3];
  133. Uint8 rgucJoystickRight[3];
  134. Uint8 ucVibrationCode;
  135. } SwitchControllerStatePacket_t;
  136. typedef struct
  137. {
  138. Sint16 sAccelX;
  139. Sint16 sAccelY;
  140. Sint16 sAccelZ;
  141. Sint16 sGyroX;
  142. Sint16 sGyroY;
  143. Sint16 sGyroZ;
  144. } SwitchControllerIMUState_t;
  145. typedef struct
  146. {
  147. SwitchControllerStatePacket_t controllerState;
  148. SwitchControllerIMUState_t imuState[3];
  149. } SwitchStatePacket_t;
  150. typedef struct
  151. {
  152. Uint32 unAddress;
  153. Uint8 ucLength;
  154. } SwitchSPIOpData_t;
  155. typedef struct
  156. {
  157. SwitchControllerStatePacket_t m_controllerState;
  158. Uint8 ucSubcommandAck;
  159. Uint8 ucSubcommandID;
  160. #define k_unSubcommandDataBytes 35
  161. union
  162. {
  163. Uint8 rgucSubcommandData[k_unSubcommandDataBytes];
  164. struct
  165. {
  166. SwitchSPIOpData_t opData;
  167. Uint8 rgucReadData[k_unSubcommandDataBytes - sizeof(SwitchSPIOpData_t)];
  168. } spiReadData;
  169. struct
  170. {
  171. Uint8 rgucFirmwareVersion[2];
  172. Uint8 ucDeviceType;
  173. Uint8 ucFiller1;
  174. Uint8 rgucMACAddress[6];
  175. Uint8 ucFiller2;
  176. Uint8 ucColorLocation;
  177. } deviceInfo;
  178. struct
  179. {
  180. SwitchSPIOpData_t opData;
  181. Uint8 rgucLeftCalibration[9];
  182. Uint8 rgucRightCalibration[9];
  183. } stickFactoryCalibration;
  184. struct
  185. {
  186. SwitchSPIOpData_t opData;
  187. Uint8 rgucLeftMagic[2];
  188. Uint8 rgucLeftCalibration[9];
  189. Uint8 rgucRightMagic[2];
  190. Uint8 rgucRightCalibration[9];
  191. } stickUserCalibration;
  192. };
  193. } SwitchSubcommandInputPacket_t;
  194. typedef struct
  195. {
  196. Uint8 ucPacketType;
  197. Uint8 ucCommandID;
  198. Uint8 ucFiller;
  199. Uint8 ucDeviceType;
  200. Uint8 rgucMACAddress[6];
  201. } SwitchProprietaryStatusPacket_t;
  202. typedef struct
  203. {
  204. Uint8 rgucData[4];
  205. } SwitchRumbleData_t;
  206. typedef struct
  207. {
  208. Uint8 ucPacketType;
  209. Uint8 ucPacketNumber;
  210. SwitchRumbleData_t rumbleData[2];
  211. } SwitchCommonOutputPacket_t;
  212. typedef struct
  213. {
  214. SwitchCommonOutputPacket_t commonData;
  215. Uint8 ucSubcommandID;
  216. Uint8 rgucSubcommandData[k_unSwitchOutputPacketDataLength - sizeof(SwitchCommonOutputPacket_t) - 1];
  217. } SwitchSubcommandOutputPacket_t;
  218. typedef struct
  219. {
  220. Uint8 ucPacketType;
  221. Uint8 ucProprietaryID;
  222. Uint8 rgucProprietaryData[k_unSwitchOutputPacketDataLength - 1 - 1];
  223. } SwitchProprietaryOutputPacket_t;
  224. #pragma pack()
  225. /* Enhanced report hint mode:
  226. * "0": enhanced features are never used
  227. * "1": enhanced features are always used
  228. * "auto": enhanced features are advertised to the application, but SDL doesn't touch the controller state unless the application explicitly requests it.
  229. */
  230. typedef enum
  231. {
  232. SWITCH_ENHANCED_REPORT_HINT_OFF,
  233. SWITCH_ENHANCED_REPORT_HINT_ON,
  234. SWITCH_ENHANCED_REPORT_HINT_AUTO
  235. } HIDAPI_Switch_EnhancedReportHint;
  236. typedef struct
  237. {
  238. SDL_HIDAPI_Device *device;
  239. SDL_Joystick *joystick;
  240. bool m_bInputOnly;
  241. bool m_bUseButtonLabels;
  242. bool m_bPlayerLights;
  243. int m_nPlayerIndex;
  244. bool m_bSyncWrite;
  245. int m_nMaxWriteAttempts;
  246. ESwitchDeviceInfoControllerType m_eControllerType;
  247. Uint8 m_nInitialInputMode;
  248. Uint8 m_nCurrentInputMode;
  249. Uint8 m_rgucMACAddress[6];
  250. Uint8 m_nCommandNumber;
  251. HIDAPI_Switch_EnhancedReportHint m_eEnhancedReportHint;
  252. bool m_bEnhancedMode;
  253. bool m_bEnhancedModeAvailable;
  254. SwitchCommonOutputPacket_t m_RumblePacket;
  255. Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength];
  256. bool m_bRumbleActive;
  257. Uint64 m_ulRumbleSent;
  258. bool m_bRumblePending;
  259. bool m_bRumbleZeroPending;
  260. Uint32 m_unRumblePending;
  261. bool m_bSensorsSupported;
  262. bool m_bReportSensors;
  263. bool m_bHasSensorData;
  264. Uint64 m_ulLastInput;
  265. Uint64 m_ulLastIMUReset;
  266. Uint64 m_ulIMUSampleTimestampNS;
  267. Uint32 m_unIMUSamples;
  268. Uint64 m_ulIMUUpdateIntervalNS;
  269. Uint64 m_ulTimestampNS;
  270. bool m_bVerticalMode;
  271. SDL_PowerState m_ePowerState;
  272. int m_nPowerPercent;
  273. SwitchInputOnlyControllerStatePacket_t m_lastInputOnlyState;
  274. SwitchSimpleStatePacket_t m_lastSimpleState;
  275. SwitchStatePacket_t m_lastFullState;
  276. struct StickCalibrationData
  277. {
  278. struct
  279. {
  280. Sint16 sCenter;
  281. Sint16 sMin;
  282. Sint16 sMax;
  283. } axis[2];
  284. } m_StickCalData[2];
  285. struct StickExtents
  286. {
  287. struct
  288. {
  289. Sint16 sMin;
  290. Sint16 sMax;
  291. } axis[2];
  292. } m_StickExtents[2], m_SimpleStickExtents[2];
  293. struct IMUScaleData
  294. {
  295. float fAccelScaleX;
  296. float fAccelScaleY;
  297. float fAccelScaleZ;
  298. float fGyroScaleX;
  299. float fGyroScaleY;
  300. float fGyroScaleZ;
  301. } m_IMUScaleData;
  302. } SDL_DriverSwitch_Context;
  303. static int ReadInput(SDL_DriverSwitch_Context *ctx)
  304. {
  305. int result;
  306. // Make sure we don't try to read at the same time a write is happening
  307. if (SDL_GetAtomicInt(&ctx->device->rumble_pending) > 0) {
  308. return 0;
  309. }
  310. result = SDL_hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
  311. // See if we can guess the initial input mode
  312. if (result > 0 && !ctx->m_bInputOnly && !ctx->m_nInitialInputMode) {
  313. switch (ctx->m_rgucReadBuffer[0]) {
  314. case k_eSwitchInputReportIDs_FullControllerState:
  315. case k_eSwitchInputReportIDs_FullControllerAndMcuState:
  316. case k_eSwitchInputReportIDs_SimpleControllerState:
  317. ctx->m_nInitialInputMode = ctx->m_rgucReadBuffer[0];
  318. break;
  319. default:
  320. break;
  321. }
  322. }
  323. return result;
  324. }
  325. static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int size)
  326. {
  327. #ifdef SWITCH_SYNCHRONOUS_WRITES
  328. return SDL_hid_write(ctx->device->dev, data, size);
  329. #else
  330. // Use the rumble thread for general asynchronous writes
  331. if (!SDL_HIDAPI_LockRumble()) {
  332. return -1;
  333. }
  334. return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size);
  335. #endif // SWITCH_SYNCHRONOUS_WRITES
  336. }
  337. static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID, const Uint8 *pBuf, Uint8 ucLen)
  338. {
  339. // Average response time for messages is ~30ms
  340. Uint64 endTicks = SDL_GetTicks() + 100;
  341. int nRead = 0;
  342. while ((nRead = ReadInput(ctx)) != -1) {
  343. if (nRead > 0) {
  344. if (ctx->m_rgucReadBuffer[0] == k_eSwitchInputReportIDs_SubcommandReply) {
  345. SwitchSubcommandInputPacket_t *reply = (SwitchSubcommandInputPacket_t *)&ctx->m_rgucReadBuffer[1];
  346. if (reply->ucSubcommandID != expectedID || !(reply->ucSubcommandAck & 0x80)) {
  347. continue;
  348. }
  349. if (reply->ucSubcommandID == k_eSwitchSubcommandIDs_SPIFlashRead) {
  350. SDL_assert(ucLen == sizeof(reply->spiReadData.opData));
  351. if (SDL_memcmp(&reply->spiReadData.opData, pBuf, ucLen) != 0) {
  352. // This was a reply for another SPI read command
  353. continue;
  354. }
  355. }
  356. return reply;
  357. }
  358. } else {
  359. SDL_Delay(1);
  360. }
  361. if (SDL_GetTicks() >= endTicks) {
  362. break;
  363. }
  364. }
  365. return NULL;
  366. }
  367. static bool ReadProprietaryReply(SDL_DriverSwitch_Context *ctx, ESwitchProprietaryCommandIDs expectedID)
  368. {
  369. // Average response time for messages is ~30ms
  370. Uint64 endTicks = SDL_GetTicks() + 100;
  371. int nRead = 0;
  372. while ((nRead = ReadInput(ctx)) != -1) {
  373. if (nRead > 0) {
  374. if (ctx->m_rgucReadBuffer[0] == k_eSwitchInputReportIDs_CommandAck && ctx->m_rgucReadBuffer[1] == expectedID) {
  375. return true;
  376. }
  377. } else {
  378. SDL_Delay(1);
  379. }
  380. if (SDL_GetTicks() >= endTicks) {
  381. break;
  382. }
  383. }
  384. return false;
  385. }
  386. static void ConstructSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs ucCommandID, const Uint8 *pBuf, Uint8 ucLen, SwitchSubcommandOutputPacket_t *outPacket)
  387. {
  388. SDL_zerop(outPacket);
  389. outPacket->commonData.ucPacketType = k_eSwitchOutputReportIDs_RumbleAndSubcommand;
  390. outPacket->commonData.ucPacketNumber = ctx->m_nCommandNumber;
  391. SDL_memcpy(outPacket->commonData.rumbleData, ctx->m_RumblePacket.rumbleData, sizeof(ctx->m_RumblePacket.rumbleData));
  392. outPacket->ucSubcommandID = ucCommandID;
  393. if (pBuf) {
  394. SDL_memcpy(outPacket->rgucSubcommandData, pBuf, ucLen);
  395. }
  396. ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF;
  397. }
  398. static bool WritePacket(SDL_DriverSwitch_Context *ctx, void *pBuf, Uint8 ucLen)
  399. {
  400. Uint8 rgucBuf[k_unSwitchMaxOutputPacketLength];
  401. const size_t unWriteSize = ctx->device->is_bluetooth ? k_unSwitchBluetoothPacketLength : k_unSwitchUSBPacketLength;
  402. if (ucLen > k_unSwitchOutputPacketDataLength) {
  403. return false;
  404. }
  405. if (ucLen < unWriteSize) {
  406. SDL_memcpy(rgucBuf, pBuf, ucLen);
  407. SDL_memset(rgucBuf + ucLen, 0, unWriteSize - ucLen);
  408. pBuf = rgucBuf;
  409. ucLen = (Uint8)unWriteSize;
  410. }
  411. if (ctx->m_bSyncWrite) {
  412. return SDL_hid_write(ctx->device->dev, (Uint8 *)pBuf, ucLen) >= 0;
  413. } else {
  414. return WriteOutput(ctx, (Uint8 *)pBuf, ucLen) >= 0;
  415. }
  416. }
  417. static bool WriteSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs ucCommandID, const Uint8 *pBuf, Uint8 ucLen, SwitchSubcommandInputPacket_t **ppReply)
  418. {
  419. SwitchSubcommandInputPacket_t *reply = NULL;
  420. int nTries;
  421. for (nTries = 1; !reply && nTries <= ctx->m_nMaxWriteAttempts; ++nTries) {
  422. SwitchSubcommandOutputPacket_t commandPacket;
  423. ConstructSubcommand(ctx, ucCommandID, pBuf, ucLen, &commandPacket);
  424. if (!WritePacket(ctx, &commandPacket, sizeof(commandPacket))) {
  425. continue;
  426. }
  427. reply = ReadSubcommandReply(ctx, ucCommandID, pBuf, ucLen);
  428. }
  429. if (ppReply) {
  430. *ppReply = reply;
  431. }
  432. return reply != NULL;
  433. }
  434. static bool WriteProprietary(SDL_DriverSwitch_Context *ctx, ESwitchProprietaryCommandIDs ucCommand, Uint8 *pBuf, Uint8 ucLen, bool waitForReply)
  435. {
  436. int nTries;
  437. for (nTries = 1; nTries <= ctx->m_nMaxWriteAttempts; ++nTries) {
  438. SwitchProprietaryOutputPacket_t packet;
  439. if ((!pBuf && ucLen > 0) || ucLen > sizeof(packet.rgucProprietaryData)) {
  440. return false;
  441. }
  442. SDL_zero(packet);
  443. packet.ucPacketType = k_eSwitchOutputReportIDs_Proprietary;
  444. packet.ucProprietaryID = ucCommand;
  445. if (pBuf) {
  446. SDL_memcpy(packet.rgucProprietaryData, pBuf, ucLen);
  447. }
  448. if (!WritePacket(ctx, &packet, sizeof(packet))) {
  449. continue;
  450. }
  451. if (!waitForReply || ReadProprietaryReply(ctx, ucCommand)) {
  452. // SDL_Log("Succeeded%s after %d tries", ctx->m_bSyncWrite ? " (sync)" : "", nTries);
  453. return true;
  454. }
  455. }
  456. // SDL_Log("Failed%s after %d tries", ctx->m_bSyncWrite ? " (sync)" : "", nTries);
  457. return false;
  458. }
  459. static Uint8 EncodeRumbleHighAmplitude(Uint16 amplitude)
  460. {
  461. /* More information about these values can be found here:
  462. * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
  463. */
  464. Uint16 hfa[101][2] = { { 0, 0x0 }, { 514, 0x2 }, { 775, 0x4 }, { 921, 0x6 }, { 1096, 0x8 }, { 1303, 0x0a }, { 1550, 0x0c }, { 1843, 0x0e }, { 2192, 0x10 }, { 2606, 0x12 }, { 3100, 0x14 }, { 3686, 0x16 }, { 4383, 0x18 }, { 5213, 0x1a }, { 6199, 0x1c }, { 7372, 0x1e }, { 7698, 0x20 }, { 8039, 0x22 }, { 8395, 0x24 }, { 8767, 0x26 }, { 9155, 0x28 }, { 9560, 0x2a }, { 9984, 0x2c }, { 10426, 0x2e }, { 10887, 0x30 }, { 11369, 0x32 }, { 11873, 0x34 }, { 12398, 0x36 }, { 12947, 0x38 }, { 13520, 0x3a }, { 14119, 0x3c }, { 14744, 0x3e }, { 15067, 0x40 }, { 15397, 0x42 }, { 15734, 0x44 }, { 16079, 0x46 }, { 16431, 0x48 }, { 16790, 0x4a }, { 17158, 0x4c }, { 17534, 0x4e }, { 17918, 0x50 }, { 18310, 0x52 }, { 18711, 0x54 }, { 19121, 0x56 }, { 19540, 0x58 }, { 19967, 0x5a }, { 20405, 0x5c }, { 20851, 0x5e }, { 21308, 0x60 }, { 21775, 0x62 }, { 22251, 0x64 }, { 22739, 0x66 }, { 23236, 0x68 }, { 23745, 0x6a }, { 24265, 0x6c }, { 24797, 0x6e }, { 25340, 0x70 }, { 25894, 0x72 }, { 26462, 0x74 }, { 27041, 0x76 }, { 27633, 0x78 }, { 28238, 0x7a }, { 28856, 0x7c }, { 29488, 0x7e }, { 30134, 0x80 }, { 30794, 0x82 }, { 31468, 0x84 }, { 32157, 0x86 }, { 32861, 0x88 }, { 33581, 0x8a }, { 34316, 0x8c }, { 35068, 0x8e }, { 35836, 0x90 }, { 36620, 0x92 }, { 37422, 0x94 }, { 38242, 0x96 }, { 39079, 0x98 }, { 39935, 0x9a }, { 40809, 0x9c }, { 41703, 0x9e }, { 42616, 0xa0 }, { 43549, 0xa2 }, { 44503, 0xa4 }, { 45477, 0xa6 }, { 46473, 0xa8 }, { 47491, 0xaa }, { 48531, 0xac }, { 49593, 0xae }, { 50679, 0xb0 }, { 51789, 0xb2 }, { 52923, 0xb4 }, { 54082, 0xb6 }, { 55266, 0xb8 }, { 56476, 0xba }, { 57713, 0xbc }, { 58977, 0xbe }, { 60268, 0xc0 }, { 61588, 0xc2 }, { 62936, 0xc4 }, { 64315, 0xc6 }, { 65535, 0xc8 } };
  465. int index = 0;
  466. for (; index < 101; index++) {
  467. if (amplitude <= hfa[index][0]) {
  468. return (Uint8)hfa[index][1];
  469. }
  470. }
  471. return (Uint8)hfa[100][1];
  472. }
  473. static Uint16 EncodeRumbleLowAmplitude(Uint16 amplitude)
  474. {
  475. /* More information about these values can be found here:
  476. * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
  477. */
  478. Uint16 lfa[101][2] = { { 0, 0x0040 }, { 514, 0x8040 }, { 775, 0x0041 }, { 921, 0x8041 }, { 1096, 0x0042 }, { 1303, 0x8042 }, { 1550, 0x0043 }, { 1843, 0x8043 }, { 2192, 0x0044 }, { 2606, 0x8044 }, { 3100, 0x0045 }, { 3686, 0x8045 }, { 4383, 0x0046 }, { 5213, 0x8046 }, { 6199, 0x0047 }, { 7372, 0x8047 }, { 7698, 0x0048 }, { 8039, 0x8048 }, { 8395, 0x0049 }, { 8767, 0x8049 }, { 9155, 0x004a }, { 9560, 0x804a }, { 9984, 0x004b }, { 10426, 0x804b }, { 10887, 0x004c }, { 11369, 0x804c }, { 11873, 0x004d }, { 12398, 0x804d }, { 12947, 0x004e }, { 13520, 0x804e }, { 14119, 0x004f }, { 14744, 0x804f }, { 15067, 0x0050 }, { 15397, 0x8050 }, { 15734, 0x0051 }, { 16079, 0x8051 }, { 16431, 0x0052 }, { 16790, 0x8052 }, { 17158, 0x0053 }, { 17534, 0x8053 }, { 17918, 0x0054 }, { 18310, 0x8054 }, { 18711, 0x0055 }, { 19121, 0x8055 }, { 19540, 0x0056 }, { 19967, 0x8056 }, { 20405, 0x0057 }, { 20851, 0x8057 }, { 21308, 0x0058 }, { 21775, 0x8058 }, { 22251, 0x0059 }, { 22739, 0x8059 }, { 23236, 0x005a }, { 23745, 0x805a }, { 24265, 0x005b }, { 24797, 0x805b }, { 25340, 0x005c }, { 25894, 0x805c }, { 26462, 0x005d }, { 27041, 0x805d }, { 27633, 0x005e }, { 28238, 0x805e }, { 28856, 0x005f }, { 29488, 0x805f }, { 30134, 0x0060 }, { 30794, 0x8060 }, { 31468, 0x0061 }, { 32157, 0x8061 }, { 32861, 0x0062 }, { 33581, 0x8062 }, { 34316, 0x0063 }, { 35068, 0x8063 }, { 35836, 0x0064 }, { 36620, 0x8064 }, { 37422, 0x0065 }, { 38242, 0x8065 }, { 39079, 0x0066 }, { 39935, 0x8066 }, { 40809, 0x0067 }, { 41703, 0x8067 }, { 42616, 0x0068 }, { 43549, 0x8068 }, { 44503, 0x0069 }, { 45477, 0x8069 }, { 46473, 0x006a }, { 47491, 0x806a }, { 48531, 0x006b }, { 49593, 0x806b }, { 50679, 0x006c }, { 51789, 0x806c }, { 52923, 0x006d }, { 54082, 0x806d }, { 55266, 0x006e }, { 56476, 0x806e }, { 57713, 0x006f }, { 58977, 0x806f }, { 60268, 0x0070 }, { 61588, 0x8070 }, { 62936, 0x0071 }, { 64315, 0x8071 }, { 65535, 0x0072 } };
  479. int index = 0;
  480. for (; index < 101; index++) {
  481. if (amplitude <= lfa[index][0]) {
  482. return lfa[index][1];
  483. }
  484. }
  485. return lfa[100][1];
  486. }
  487. static void SetNeutralRumble(SDL_HIDAPI_Device *device, SwitchRumbleData_t *pRumble)
  488. {
  489. bool bStandardNeutralValue;
  490. if (device->vendor_id == USB_VENDOR_NINTENDO &&
  491. device->product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
  492. // The 8BitDo 64 Bluetooth Controller rumbles at startup with the standard neutral value,
  493. // so we'll use a 0 amplitude value instead.
  494. bStandardNeutralValue = false;
  495. } else {
  496. // The KingKong2 PRO Controller doesn't initialize correctly with a 0 amplitude value
  497. // over Bluetooth, so we'll use the standard value in all other cases.
  498. bStandardNeutralValue = true;
  499. }
  500. if (bStandardNeutralValue) {
  501. pRumble->rgucData[0] = 0x00;
  502. pRumble->rgucData[1] = 0x01;
  503. pRumble->rgucData[2] = 0x40;
  504. pRumble->rgucData[3] = 0x40;
  505. } else {
  506. pRumble->rgucData[0] = 0x00;
  507. pRumble->rgucData[1] = 0x00;
  508. pRumble->rgucData[2] = 0x01;
  509. pRumble->rgucData[3] = 0x40;
  510. }
  511. }
  512. static void EncodeRumble(SDL_HIDAPI_Device *device, SwitchRumbleData_t *pRumble, Uint16 usHighFreq, Uint8 ucHighFreqAmp, Uint8 ucLowFreq, Uint16 usLowFreqAmp)
  513. {
  514. if (ucHighFreqAmp > 0 || usLowFreqAmp > 0) {
  515. // High-band frequency and low-band amplitude are actually nine-bits each so they
  516. // take a bit from the high-band amplitude and low-band frequency bytes respectively
  517. pRumble->rgucData[0] = usHighFreq & 0xFF;
  518. pRumble->rgucData[1] = ucHighFreqAmp | ((usHighFreq >> 8) & 0x01);
  519. pRumble->rgucData[2] = ucLowFreq | ((usLowFreqAmp >> 8) & 0x80);
  520. pRumble->rgucData[3] = usLowFreqAmp & 0xFF;
  521. #ifdef DEBUG_RUMBLE
  522. SDL_Log("Freq: %.2X %.2X %.2X, Amp: %.2X %.2X %.2X",
  523. usHighFreq & 0xFF, ((usHighFreq >> 8) & 0x01), ucLowFreq,
  524. ucHighFreqAmp, ((usLowFreqAmp >> 8) & 0x80), usLowFreqAmp & 0xFF);
  525. #endif
  526. } else {
  527. SetNeutralRumble(device, pRumble);
  528. }
  529. }
  530. static bool WriteRumble(SDL_DriverSwitch_Context *ctx)
  531. {
  532. /* Write into m_RumblePacket rather than a temporary buffer to allow the current rumble state
  533. * to be retained for subsequent rumble or subcommand packets sent to the controller
  534. */
  535. ctx->m_RumblePacket.ucPacketType = k_eSwitchOutputReportIDs_Rumble;
  536. ctx->m_RumblePacket.ucPacketNumber = ctx->m_nCommandNumber;
  537. ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF;
  538. // Refresh the rumble state periodically
  539. ctx->m_ulRumbleSent = SDL_GetTicks();
  540. return WritePacket(ctx, (Uint8 *)&ctx->m_RumblePacket, sizeof(ctx->m_RumblePacket));
  541. }
  542. static ESwitchDeviceInfoControllerType CalculateControllerType(SDL_DriverSwitch_Context *ctx, ESwitchDeviceInfoControllerType eControllerType)
  543. {
  544. SDL_HIDAPI_Device *device = ctx->device;
  545. // The N64 controller reports as a Pro controller over USB
  546. if (eControllerType == k_eSwitchDeviceInfoControllerType_ProController &&
  547. device->product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
  548. eControllerType = k_eSwitchDeviceInfoControllerType_N64;
  549. }
  550. if (eControllerType == k_eSwitchDeviceInfoControllerType_Unknown) {
  551. // This might be a Joy-Con that's missing from a charging grip slot
  552. if (device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
  553. if (device->interface_number == 1) {
  554. eControllerType = k_eSwitchDeviceInfoControllerType_JoyConLeft;
  555. } else {
  556. eControllerType = k_eSwitchDeviceInfoControllerType_JoyConRight;
  557. }
  558. }
  559. }
  560. return eControllerType;
  561. }
  562. static bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx)
  563. {
  564. SwitchSubcommandInputPacket_t *reply = NULL;
  565. if (ctx->device->is_bluetooth) {
  566. if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) {
  567. // Byte 2: Controller ID (1=LJC, 2=RJC, 3=Pro)
  568. ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType);
  569. // Bytes 4-9: MAC address (big-endian)
  570. SDL_memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
  571. return true;
  572. }
  573. } else {
  574. if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, true)) {
  575. SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0];
  576. size_t i;
  577. ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)status->ucDeviceType);
  578. for (i = 0; i < sizeof(ctx->m_rgucMACAddress); ++i) {
  579. ctx->m_rgucMACAddress[i] = status->rgucMACAddress[sizeof(ctx->m_rgucMACAddress) - i - 1];
  580. }
  581. return true;
  582. }
  583. }
  584. return false;
  585. }
  586. static bool BTrySetupUSB(SDL_DriverSwitch_Context *ctx)
  587. {
  588. /* We have to send a connection handshake to the controller when communicating over USB
  589. * before we're able to send it other commands. Luckily this command is not supported
  590. * over Bluetooth, so we can use the controller's lack of response as a way to
  591. * determine if the connection is over USB or Bluetooth
  592. */
  593. if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Handshake, NULL, 0, true)) {
  594. return false;
  595. }
  596. if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_HighSpeed, NULL, 0, true)) {
  597. // The 8BitDo M30 and SF30 Pro don't respond to this command, but otherwise work correctly
  598. // return false;
  599. }
  600. if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Handshake, NULL, 0, true)) {
  601. // This fails on the right Joy-Con when plugged into the charging grip
  602. // return false;
  603. }
  604. if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, false)) {
  605. return false;
  606. }
  607. return true;
  608. }
  609. static bool SetVibrationEnabled(SDL_DriverSwitch_Context *ctx, Uint8 enabled)
  610. {
  611. return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_EnableVibration, &enabled, sizeof(enabled), NULL);
  612. }
  613. static bool SetInputMode(SDL_DriverSwitch_Context *ctx, Uint8 input_mode)
  614. {
  615. #ifdef FORCE_SIMPLE_REPORTS
  616. input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
  617. #endif
  618. #ifdef FORCE_FULL_REPORTS
  619. input_mode = k_eSwitchInputReportIDs_FullControllerState;
  620. #endif
  621. if (input_mode == ctx->m_nCurrentInputMode) {
  622. return true;
  623. } else {
  624. ctx->m_nCurrentInputMode = input_mode;
  625. return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetInputReportMode, &input_mode, sizeof(input_mode), NULL);
  626. }
  627. }
  628. static bool SetHomeLED(SDL_DriverSwitch_Context *ctx, Uint8 brightness)
  629. {
  630. Uint8 ucLedIntensity = 0;
  631. Uint8 rgucBuffer[4];
  632. if (brightness > 0) {
  633. if (brightness < 65) {
  634. ucLedIntensity = (brightness + 5) / 10;
  635. } else {
  636. ucLedIntensity = (Uint8)SDL_ceilf(0xF * SDL_powf((float)brightness / 100.f, 2.13f));
  637. }
  638. }
  639. rgucBuffer[0] = (0x0 << 4) | 0x1; // 0 mini cycles (besides first), cycle duration 8ms
  640. rgucBuffer[1] = ((ucLedIntensity & 0xF) << 4) | 0x0; // LED start intensity (0x0-0xF), 0 cycles (LED stays on at start intensity after first cycle)
  641. rgucBuffer[2] = ((ucLedIntensity & 0xF) << 4) | 0x0; // First cycle LED intensity, 0x0 intensity for second cycle
  642. rgucBuffer[3] = (0x0 << 4) | 0x0; // 8ms fade transition to first cycle, 8ms first cycle LED duration
  643. return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetHomeLight, rgucBuffer, sizeof(rgucBuffer), NULL);
  644. }
  645. static void SDLCALL SDL_HomeLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  646. {
  647. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata;
  648. if (hint && *hint) {
  649. int value;
  650. if (SDL_strchr(hint, '.') != NULL) {
  651. value = (int)(100.0f * SDL_atof(hint));
  652. if (value > 255) {
  653. value = 255;
  654. }
  655. } else if (SDL_GetStringBoolean(hint, true)) {
  656. value = 100;
  657. } else {
  658. value = 0;
  659. }
  660. SetHomeLED(ctx, (Uint8)value);
  661. }
  662. }
  663. static void UpdateSlotLED(SDL_DriverSwitch_Context *ctx)
  664. {
  665. if (!ctx->m_bInputOnly) {
  666. Uint8 led_data = 0;
  667. const Uint8 player_pattern[] = { 0x1, 0x3, 0x7, 0xf, 0x9, 0x5, 0xd, 0x6 };
  668. if (ctx->m_bPlayerLights && ctx->m_nPlayerIndex >= 0) {
  669. led_data = player_pattern[ctx->m_nPlayerIndex % 8];
  670. }
  671. WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetPlayerLights, &led_data, sizeof(led_data), NULL);
  672. }
  673. }
  674. static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  675. {
  676. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata;
  677. bool bPlayerLights = SDL_GetStringBoolean(hint, true);
  678. if (bPlayerLights != ctx->m_bPlayerLights) {
  679. ctx->m_bPlayerLights = bPlayerLights;
  680. UpdateSlotLED(ctx);
  681. HIDAPI_UpdateDeviceProperties(ctx->device);
  682. }
  683. }
  684. static void GetInitialInputMode(SDL_DriverSwitch_Context *ctx)
  685. {
  686. if (!ctx->m_nInitialInputMode) {
  687. // This will set the initial input mode if it can
  688. ReadInput(ctx);
  689. }
  690. }
  691. static Uint8 GetDefaultInputMode(SDL_DriverSwitch_Context *ctx)
  692. {
  693. Uint8 input_mode;
  694. // Determine the desired input mode
  695. if (ctx->m_nInitialInputMode) {
  696. input_mode = ctx->m_nInitialInputMode;
  697. } else {
  698. if (ctx->device->is_bluetooth) {
  699. input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
  700. } else {
  701. input_mode = k_eSwitchInputReportIDs_FullControllerState;
  702. }
  703. }
  704. switch (ctx->m_eEnhancedReportHint) {
  705. case SWITCH_ENHANCED_REPORT_HINT_OFF:
  706. input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
  707. break;
  708. case SWITCH_ENHANCED_REPORT_HINT_ON:
  709. if (input_mode == k_eSwitchInputReportIDs_SimpleControllerState) {
  710. input_mode = k_eSwitchInputReportIDs_FullControllerState;
  711. }
  712. break;
  713. case SWITCH_ENHANCED_REPORT_HINT_AUTO:
  714. /* Joy-Con controllers switch their thumbsticks into D-pad mode in simple mode,
  715. * so let's enable full controller state for them.
  716. */
  717. if (ctx->device->vendor_id == USB_VENDOR_NINTENDO &&
  718. (ctx->device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT ||
  719. ctx->device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT)) {
  720. input_mode = k_eSwitchInputReportIDs_FullControllerState;
  721. }
  722. break;
  723. }
  724. // Wired controllers break if they are put into simple controller state
  725. if (input_mode == k_eSwitchInputReportIDs_SimpleControllerState &&
  726. !ctx->device->is_bluetooth) {
  727. input_mode = k_eSwitchInputReportIDs_FullControllerState;
  728. }
  729. return input_mode;
  730. }
  731. static Uint8 GetSensorInputMode(SDL_DriverSwitch_Context *ctx)
  732. {
  733. Uint8 input_mode;
  734. // Determine the desired input mode
  735. if (!ctx->m_nInitialInputMode ||
  736. ctx->m_nInitialInputMode == k_eSwitchInputReportIDs_SimpleControllerState) {
  737. input_mode = k_eSwitchInputReportIDs_FullControllerState;
  738. } else {
  739. input_mode = ctx->m_nInitialInputMode;
  740. }
  741. return input_mode;
  742. }
  743. static void UpdateInputMode(SDL_DriverSwitch_Context *ctx)
  744. {
  745. Uint8 input_mode;
  746. if (ctx->m_bReportSensors) {
  747. input_mode = GetSensorInputMode(ctx);
  748. } else {
  749. input_mode = GetDefaultInputMode(ctx);
  750. }
  751. SetInputMode(ctx, input_mode);
  752. }
  753. static void SetEnhancedModeAvailable(SDL_DriverSwitch_Context *ctx)
  754. {
  755. if (ctx->m_bEnhancedModeAvailable) {
  756. return;
  757. }
  758. ctx->m_bEnhancedModeAvailable = true;
  759. if (ctx->m_bSensorsSupported) {
  760. // Use the right sensor in the combined Joy-Con pair
  761. if (!ctx->device->parent ||
  762. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  763. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 200.0f);
  764. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 200.0f);
  765. }
  766. if (ctx->device->parent &&
  767. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
  768. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO_L, 200.0f);
  769. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL_L, 200.0f);
  770. }
  771. if (ctx->device->parent &&
  772. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  773. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO_R, 200.0f);
  774. SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL_R, 200.0f);
  775. }
  776. }
  777. }
  778. static void SetEnhancedReportHint(SDL_DriverSwitch_Context *ctx, HIDAPI_Switch_EnhancedReportHint eEnhancedReportHint)
  779. {
  780. ctx->m_eEnhancedReportHint = eEnhancedReportHint;
  781. switch (eEnhancedReportHint) {
  782. case SWITCH_ENHANCED_REPORT_HINT_OFF:
  783. ctx->m_bEnhancedMode = false;
  784. break;
  785. case SWITCH_ENHANCED_REPORT_HINT_ON:
  786. SetEnhancedModeAvailable(ctx);
  787. ctx->m_bEnhancedMode = true;
  788. break;
  789. case SWITCH_ENHANCED_REPORT_HINT_AUTO:
  790. SetEnhancedModeAvailable(ctx);
  791. break;
  792. }
  793. UpdateInputMode(ctx);
  794. }
  795. static void UpdateEnhancedModeOnEnhancedReport(SDL_DriverSwitch_Context *ctx)
  796. {
  797. if (ctx->m_eEnhancedReportHint == SWITCH_ENHANCED_REPORT_HINT_AUTO) {
  798. SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_ON);
  799. }
  800. }
  801. static void UpdateEnhancedModeOnApplicationUsage(SDL_DriverSwitch_Context *ctx)
  802. {
  803. if (ctx->m_eEnhancedReportHint == SWITCH_ENHANCED_REPORT_HINT_AUTO) {
  804. SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_ON);
  805. }
  806. }
  807. static void SDLCALL SDL_EnhancedReportsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
  808. {
  809. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata;
  810. if (hint && SDL_strcasecmp(hint, "auto") == 0) {
  811. SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_AUTO);
  812. } else if (SDL_GetStringBoolean(hint, true)) {
  813. SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_ON);
  814. } else {
  815. SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_OFF);
  816. }
  817. }
  818. static bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, bool enabled)
  819. {
  820. Uint8 imu_data = enabled ? 1 : 0;
  821. return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_EnableIMU, &imu_data, sizeof(imu_data), NULL);
  822. }
  823. static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
  824. {
  825. Uint8 *pLeftStickCal = NULL;
  826. Uint8 *pRightStickCal = NULL;
  827. size_t stick, axis;
  828. SwitchSubcommandInputPacket_t *user_reply = NULL;
  829. SwitchSubcommandInputPacket_t *factory_reply = NULL;
  830. SwitchSPIOpData_t readUserParams;
  831. SwitchSPIOpData_t readFactoryParams;
  832. Uint8 userParamsReadSuccessCount = 0;
  833. // Read User Calibration Info
  834. readUserParams.unAddress = k_unSPIStickUserCalibrationStartOffset;
  835. readUserParams.ucLength = k_unSPIStickUserCalibrationLength;
  836. // This isn't readable on all controllers, so ignore failure
  837. WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readUserParams, sizeof(readUserParams), &user_reply);
  838. // Read Factory Calibration Info
  839. readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
  840. readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
  841. // Automatically select the user calibration if magic bytes are set
  842. if (user_reply && user_reply->stickUserCalibration.rgucLeftMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucLeftMagic[1] == 0xA1) {
  843. userParamsReadSuccessCount += 1;
  844. pLeftStickCal = user_reply->stickUserCalibration.rgucLeftCalibration;
  845. }
  846. if (user_reply && user_reply->stickUserCalibration.rgucRightMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucRightMagic[1] == 0xA1) {
  847. userParamsReadSuccessCount += 1;
  848. pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration;
  849. }
  850. // Only read the factory calibration info if we failed to receive the correct magic bytes
  851. if (userParamsReadSuccessCount < 2) {
  852. // Read Factory Calibration Info
  853. readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
  854. readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
  855. const int MAX_ATTEMPTS = 3;
  856. for (int attempt = 0;; ++attempt) {
  857. if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
  858. return false;
  859. }
  860. if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
  861. // We successfully read the calibration data
  862. pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
  863. pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
  864. break;
  865. }
  866. if (attempt == MAX_ATTEMPTS) {
  867. return false;
  868. }
  869. }
  870. }
  871. // If we still don't have calibration data, return false
  872. if (pLeftStickCal == NULL || pRightStickCal == NULL)
  873. {
  874. return false;
  875. }
  876. /* Stick calibration values are 12-bits each and are packed by bit
  877. * For whatever reason the fields are in a different order for each stick
  878. * Left: X-Max, Y-Max, X-Center, Y-Center, X-Min, Y-Min
  879. * Right: X-Center, Y-Center, X-Min, Y-Min, X-Max, Y-Max
  880. */
  881. // Left stick
  882. ctx->m_StickCalData[0].axis[0].sMax = ((pLeftStickCal[1] << 8) & 0xF00) | pLeftStickCal[0]; // X Axis max above center
  883. ctx->m_StickCalData[0].axis[1].sMax = (pLeftStickCal[2] << 4) | (pLeftStickCal[1] >> 4); // Y Axis max above center
  884. ctx->m_StickCalData[0].axis[0].sCenter = ((pLeftStickCal[4] << 8) & 0xF00) | pLeftStickCal[3]; // X Axis center
  885. ctx->m_StickCalData[0].axis[1].sCenter = (pLeftStickCal[5] << 4) | (pLeftStickCal[4] >> 4); // Y Axis center
  886. ctx->m_StickCalData[0].axis[0].sMin = ((pLeftStickCal[7] << 8) & 0xF00) | pLeftStickCal[6]; // X Axis min below center
  887. ctx->m_StickCalData[0].axis[1].sMin = (pLeftStickCal[8] << 4) | (pLeftStickCal[7] >> 4); // Y Axis min below center
  888. // Right stick
  889. ctx->m_StickCalData[1].axis[0].sCenter = ((pRightStickCal[1] << 8) & 0xF00) | pRightStickCal[0]; // X Axis center
  890. ctx->m_StickCalData[1].axis[1].sCenter = (pRightStickCal[2] << 4) | (pRightStickCal[1] >> 4); // Y Axis center
  891. ctx->m_StickCalData[1].axis[0].sMin = ((pRightStickCal[4] << 8) & 0xF00) | pRightStickCal[3]; // X Axis min below center
  892. ctx->m_StickCalData[1].axis[1].sMin = (pRightStickCal[5] << 4) | (pRightStickCal[4] >> 4); // Y Axis min below center
  893. ctx->m_StickCalData[1].axis[0].sMax = ((pRightStickCal[7] << 8) & 0xF00) | pRightStickCal[6]; // X Axis max above center
  894. ctx->m_StickCalData[1].axis[1].sMax = (pRightStickCal[8] << 4) | (pRightStickCal[7] >> 4); // Y Axis max above center
  895. // Filter out any values that were uninitialized (0xFFF) in the SPI read
  896. for (stick = 0; stick < 2; ++stick) {
  897. for (axis = 0; axis < 2; ++axis) {
  898. if (ctx->m_StickCalData[stick].axis[axis].sCenter == 0xFFF) {
  899. ctx->m_StickCalData[stick].axis[axis].sCenter = 2048;
  900. }
  901. if (ctx->m_StickCalData[stick].axis[axis].sMax == 0xFFF) {
  902. ctx->m_StickCalData[stick].axis[axis].sMax = (Sint16)(ctx->m_StickCalData[stick].axis[axis].sCenter * 0.7f);
  903. }
  904. if (ctx->m_StickCalData[stick].axis[axis].sMin == 0xFFF) {
  905. ctx->m_StickCalData[stick].axis[axis].sMin = (Sint16)(ctx->m_StickCalData[stick].axis[axis].sCenter * 0.7f);
  906. }
  907. }
  908. }
  909. for (stick = 0; stick < 2; ++stick) {
  910. for (axis = 0; axis < 2; ++axis) {
  911. ctx->m_StickExtents[stick].axis[axis].sMin = -(Sint16)(ctx->m_StickCalData[stick].axis[axis].sMin * 0.7f);
  912. ctx->m_StickExtents[stick].axis[axis].sMax = (Sint16)(ctx->m_StickCalData[stick].axis[axis].sMax * 0.7f);
  913. }
  914. }
  915. for (stick = 0; stick < 2; ++stick) {
  916. for (axis = 0; axis < 2; ++axis) {
  917. ctx->m_SimpleStickExtents[stick].axis[axis].sMin = (Sint16)(SDL_MIN_SINT16 * 0.5f);
  918. ctx->m_SimpleStickExtents[stick].axis[axis].sMax = (Sint16)(SDL_MAX_SINT16 * 0.5f);
  919. }
  920. }
  921. return true;
  922. }
  923. static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
  924. {
  925. SwitchSubcommandInputPacket_t *reply = NULL;
  926. // Read Calibration Info
  927. SwitchSPIOpData_t readParams;
  928. readParams.unAddress = k_unSPIIMUScaleStartOffset;
  929. readParams.ucLength = k_unSPIIMUScaleLength;
  930. if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readParams, sizeof(readParams), &reply)) {
  931. Uint8 *pIMUScale;
  932. Sint16 sAccelRawX, sAccelRawY, sAccelRawZ, sGyroRawX, sGyroRawY, sGyroRawZ;
  933. Sint16 sAccelSensCoeffX, sAccelSensCoeffY, sAccelSensCoeffZ;
  934. Sint16 sGyroSensCoeffX, sGyroSensCoeffY, sGyroSensCoeffZ;
  935. // IMU scale gives us multipliers for converting raw values to real world values
  936. pIMUScale = reply->spiReadData.rgucReadData;
  937. sAccelRawX = (pIMUScale[1] << 8) | pIMUScale[0];
  938. sAccelRawY = (pIMUScale[3] << 8) | pIMUScale[2];
  939. sAccelRawZ = (pIMUScale[5] << 8) | pIMUScale[4];
  940. sAccelSensCoeffX = (pIMUScale[7] << 8) | pIMUScale[6];
  941. sAccelSensCoeffY = (pIMUScale[9] << 8) | pIMUScale[8];
  942. sAccelSensCoeffZ = (pIMUScale[11] << 8) | pIMUScale[10];
  943. sGyroRawX = (pIMUScale[13] << 8) | pIMUScale[12];
  944. sGyroRawY = (pIMUScale[15] << 8) | pIMUScale[14];
  945. sGyroRawZ = (pIMUScale[17] << 8) | pIMUScale[16];
  946. sGyroSensCoeffX = (pIMUScale[19] << 8) | pIMUScale[18];
  947. sGyroSensCoeffY = (pIMUScale[21] << 8) | pIMUScale[20];
  948. sGyroSensCoeffZ = (pIMUScale[23] << 8) | pIMUScale[22];
  949. // Check for user calibration data. If it's present and set, it'll override the factory settings
  950. readParams.unAddress = k_unSPIIMUUserScaleStartOffset;
  951. readParams.ucLength = k_unSPIIMUUserScaleLength;
  952. if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readParams, sizeof(readParams), &reply) && (pIMUScale[0] | pIMUScale[1] << 8) == 0xA1B2) {
  953. pIMUScale = reply->spiReadData.rgucReadData;
  954. sAccelRawX = (pIMUScale[3] << 8) | pIMUScale[2];
  955. sAccelRawY = (pIMUScale[5] << 8) | pIMUScale[4];
  956. sAccelRawZ = (pIMUScale[7] << 8) | pIMUScale[6];
  957. sGyroRawX = (pIMUScale[15] << 8) | pIMUScale[14];
  958. sGyroRawY = (pIMUScale[17] << 8) | pIMUScale[16];
  959. sGyroRawZ = (pIMUScale[19] << 8) | pIMUScale[18];
  960. }
  961. // Accelerometer scale
  962. ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffX - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
  963. ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffY - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
  964. ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffZ - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
  965. // Gyro scale
  966. ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffX - (float)sGyroRawX) * SDL_PI_F / 180.0f;
  967. ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffY - (float)sGyroRawY) * SDL_PI_F / 180.0f;
  968. ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffZ - (float)sGyroRawZ) * SDL_PI_F / 180.0f;
  969. } else {
  970. // Use default values
  971. const float accelScale = SDL_STANDARD_GRAVITY / SWITCH_ACCEL_SCALE;
  972. const float gyroScale = SDL_PI_F / 180.0f / SWITCH_GYRO_SCALE;
  973. ctx->m_IMUScaleData.fAccelScaleX = accelScale;
  974. ctx->m_IMUScaleData.fAccelScaleY = accelScale;
  975. ctx->m_IMUScaleData.fAccelScaleZ = accelScale;
  976. ctx->m_IMUScaleData.fGyroScaleX = gyroScale;
  977. ctx->m_IMUScaleData.fGyroScaleY = gyroScale;
  978. ctx->m_IMUScaleData.fGyroScaleZ = gyroScale;
  979. }
  980. return true;
  981. }
  982. static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
  983. {
  984. sRawValue -= ctx->m_StickCalData[nStick].axis[nAxis].sCenter;
  985. if (sRawValue >= 0) {
  986. if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
  987. ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
  988. }
  989. return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
  990. } else {
  991. if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
  992. ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
  993. }
  994. return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
  995. }
  996. }
  997. static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
  998. {
  999. // 0x8000 is the neutral value for all joystick axes
  1000. const Uint16 usJoystickCenter = 0x8000;
  1001. sRawValue -= usJoystickCenter;
  1002. if (sRawValue >= 0) {
  1003. if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
  1004. ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
  1005. }
  1006. return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
  1007. } else {
  1008. if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) {
  1009. ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
  1010. }
  1011. return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
  1012. }
  1013. }
  1014. static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
  1015. {
  1016. if (ctx->m_bUseButtonLabels) {
  1017. // Use button labels instead of positions, e.g. Nintendo Online Classic controllers
  1018. switch (button) {
  1019. case SDL_GAMEPAD_BUTTON_SOUTH:
  1020. return SDL_GAMEPAD_BUTTON_EAST;
  1021. case SDL_GAMEPAD_BUTTON_EAST:
  1022. return SDL_GAMEPAD_BUTTON_SOUTH;
  1023. case SDL_GAMEPAD_BUTTON_WEST:
  1024. return SDL_GAMEPAD_BUTTON_NORTH;
  1025. case SDL_GAMEPAD_BUTTON_NORTH:
  1026. return SDL_GAMEPAD_BUTTON_WEST;
  1027. default:
  1028. break;
  1029. }
  1030. }
  1031. return button;
  1032. }
  1033. static int GetMaxWriteAttempts(SDL_HIDAPI_Device *device)
  1034. {
  1035. if (device->vendor_id == USB_VENDOR_NINTENDO &&
  1036. device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
  1037. // This device is a little slow and we know we're always on USB
  1038. return 20;
  1039. } else {
  1040. return 5;
  1041. }
  1042. }
  1043. static ESwitchDeviceInfoControllerType ReadJoyConControllerType(SDL_HIDAPI_Device *device)
  1044. {
  1045. ESwitchDeviceInfoControllerType eControllerType = k_eSwitchDeviceInfoControllerType_Unknown;
  1046. const int MAX_ATTEMPTS = 1; // Don't try too long, in case this is a zombie Bluetooth controller
  1047. int attempts = 0;
  1048. // Create enough of a context to read the controller type from the device
  1049. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx));
  1050. if (ctx) {
  1051. ctx->device = device;
  1052. ctx->m_bSyncWrite = true;
  1053. ctx->m_nMaxWriteAttempts = GetMaxWriteAttempts(device);
  1054. for ( ; ; ) {
  1055. ++attempts;
  1056. if (device->is_bluetooth) {
  1057. SwitchSubcommandInputPacket_t *reply = NULL;
  1058. if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) {
  1059. eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType);
  1060. }
  1061. } else {
  1062. if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, true)) {
  1063. SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0];
  1064. eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)status->ucDeviceType);
  1065. }
  1066. }
  1067. if (eControllerType == k_eSwitchDeviceInfoControllerType_Unknown && attempts < MAX_ATTEMPTS) {
  1068. // Wait a bit and try again
  1069. SDL_Delay(100);
  1070. continue;
  1071. }
  1072. break;
  1073. }
  1074. SDL_free(ctx);
  1075. }
  1076. return eControllerType;
  1077. }
  1078. static bool HasHomeLED(SDL_DriverSwitch_Context *ctx)
  1079. {
  1080. Uint16 vendor_id = ctx->device->vendor_id;
  1081. Uint16 product_id = ctx->device->product_id;
  1082. // The Power A Nintendo Switch Pro controllers don't have a Home LED
  1083. if (vendor_id == 0 && product_id == 0) {
  1084. return false;
  1085. }
  1086. // HORI Wireless Switch Pad
  1087. if (vendor_id == 0x0f0d && product_id == 0x00f6) {
  1088. return false;
  1089. }
  1090. // Third party controllers don't have a home LED and will shut off if we try to set it
  1091. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_Unknown ||
  1092. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_LicProController) {
  1093. return false;
  1094. }
  1095. // The Nintendo Online classic controllers don't have a Home LED
  1096. if (vendor_id == USB_VENDOR_NINTENDO &&
  1097. ctx->m_eControllerType > k_eSwitchDeviceInfoControllerType_ProController) {
  1098. return false;
  1099. }
  1100. return true;
  1101. }
  1102. static bool AlwaysUsesLabels(Uint16 vendor_id, Uint16 product_id, ESwitchDeviceInfoControllerType eControllerType)
  1103. {
  1104. // Some controllers don't have a diamond button configuration, so should always use labels
  1105. if (SDL_IsJoystickGameCube(vendor_id, product_id)) {
  1106. return true;
  1107. }
  1108. switch (eControllerType) {
  1109. case k_eSwitchDeviceInfoControllerType_HVCLeft:
  1110. case k_eSwitchDeviceInfoControllerType_HVCRight:
  1111. case k_eSwitchDeviceInfoControllerType_NESLeft:
  1112. case k_eSwitchDeviceInfoControllerType_NESRight:
  1113. case k_eSwitchDeviceInfoControllerType_N64:
  1114. case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
  1115. return true;
  1116. default:
  1117. return false;
  1118. }
  1119. }
  1120. static void HIDAPI_DriverNintendoClassic_RegisterHints(SDL_HintCallback callback, void *userdata)
  1121. {
  1122. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata);
  1123. }
  1124. static void HIDAPI_DriverNintendoClassic_UnregisterHints(SDL_HintCallback callback, void *userdata)
  1125. {
  1126. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata);
  1127. }
  1128. static bool HIDAPI_DriverNintendoClassic_IsEnabled(void)
  1129. {
  1130. return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT));
  1131. }
  1132. static bool HIDAPI_DriverNintendoClassic_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
  1133. {
  1134. if (vendor_id == USB_VENDOR_NINTENDO) {
  1135. if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
  1136. if (SDL_strncmp(name, "NES Controller", 14) == 0 ||
  1137. SDL_strncmp(name, "HVC Controller", 14) == 0) {
  1138. return true;
  1139. }
  1140. }
  1141. if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
  1142. return true;
  1143. }
  1144. if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) {
  1145. return true;
  1146. }
  1147. if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
  1148. return true;
  1149. }
  1150. }
  1151. return false;
  1152. }
  1153. static void HIDAPI_DriverJoyCons_RegisterHints(SDL_HintCallback callback, void *userdata)
  1154. {
  1155. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata);
  1156. }
  1157. static void HIDAPI_DriverJoyCons_UnregisterHints(SDL_HintCallback callback, void *userdata)
  1158. {
  1159. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata);
  1160. }
  1161. static bool HIDAPI_DriverJoyCons_IsEnabled(void)
  1162. {
  1163. return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT));
  1164. }
  1165. static bool HIDAPI_DriverJoyCons_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
  1166. {
  1167. if (vendor_id == USB_VENDOR_NINTENDO) {
  1168. if (product_id == USB_PRODUCT_NINTENDO_SWITCH_PRO && device && device->dev) {
  1169. // This might be a Kinvoca Joy-Con that reports VID/PID as a Switch Pro controller
  1170. ESwitchDeviceInfoControllerType eControllerType = ReadJoyConControllerType(device);
  1171. if (eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
  1172. eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  1173. return true;
  1174. }
  1175. }
  1176. if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT ||
  1177. product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT ||
  1178. product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
  1179. return true;
  1180. }
  1181. }
  1182. return false;
  1183. }
  1184. static void HIDAPI_DriverSwitch_RegisterHints(SDL_HintCallback callback, void *userdata)
  1185. {
  1186. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata);
  1187. }
  1188. static void HIDAPI_DriverSwitch_UnregisterHints(SDL_HintCallback callback, void *userdata)
  1189. {
  1190. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata);
  1191. }
  1192. static bool HIDAPI_DriverSwitch_IsEnabled(void)
  1193. {
  1194. return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT));
  1195. }
  1196. static bool HIDAPI_DriverSwitch_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
  1197. {
  1198. /* The HORI Wireless Switch Pad enumerates as a HID device when connected via USB
  1199. with the same VID/PID as when connected over Bluetooth but doesn't actually
  1200. support communication over USB. The most reliable way to block this without allowing the
  1201. controller to continually attempt to reconnect is to filter it out by manufacturer/product string.
  1202. Note that the controller does have a different product string when connected over Bluetooth.
  1203. */
  1204. if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) {
  1205. return false;
  1206. }
  1207. // If it's handled by another driver, it's not handled here
  1208. if (HIDAPI_DriverNintendoClassic_IsSupportedDevice(device, name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol) ||
  1209. HIDAPI_DriverJoyCons_IsSupportedDevice(device, name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol)) {
  1210. return false;
  1211. }
  1212. if (type != SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO) {
  1213. return false;
  1214. }
  1215. // The Nintendo Switch 2 Pro uses another driver
  1216. if (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH2_PRO) {
  1217. return false;
  1218. }
  1219. return true;
  1220. }
  1221. static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
  1222. {
  1223. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1224. if (ctx->m_bInputOnly) {
  1225. if (SDL_IsJoystickGameCube(device->vendor_id, device->product_id)) {
  1226. device->type = SDL_GAMEPAD_TYPE_GAMECUBE;
  1227. }
  1228. } else {
  1229. char serial[18];
  1230. switch (ctx->m_eControllerType) {
  1231. case k_eSwitchDeviceInfoControllerType_JoyConLeft:
  1232. HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)");
  1233. HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT);
  1234. device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
  1235. break;
  1236. case k_eSwitchDeviceInfoControllerType_JoyConRight:
  1237. HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)");
  1238. HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT);
  1239. device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
  1240. break;
  1241. case k_eSwitchDeviceInfoControllerType_ProController:
  1242. case k_eSwitchDeviceInfoControllerType_LicProController:
  1243. HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
  1244. HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_PRO);
  1245. device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
  1246. break;
  1247. case k_eSwitchDeviceInfoControllerType_HVCLeft:
  1248. HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (1)");
  1249. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1250. break;
  1251. case k_eSwitchDeviceInfoControllerType_HVCRight:
  1252. HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (2)");
  1253. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1254. break;
  1255. case k_eSwitchDeviceInfoControllerType_NESLeft:
  1256. HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)");
  1257. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1258. break;
  1259. case k_eSwitchDeviceInfoControllerType_NESRight:
  1260. HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)");
  1261. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1262. break;
  1263. case k_eSwitchDeviceInfoControllerType_SNES:
  1264. HIDAPI_SetDeviceName(device, "Nintendo SNES Controller");
  1265. HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SNES_CONTROLLER);
  1266. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1267. break;
  1268. case k_eSwitchDeviceInfoControllerType_N64:
  1269. HIDAPI_SetDeviceName(device, "Nintendo N64 Controller");
  1270. HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_N64_CONTROLLER);
  1271. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1272. break;
  1273. case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
  1274. HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller");
  1275. HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER);
  1276. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1277. break;
  1278. case k_eSwitchDeviceInfoControllerType_Unknown:
  1279. // We couldn't read the device info for this controller, might not be fully compliant
  1280. if (device->vendor_id == USB_VENDOR_NINTENDO) {
  1281. switch (device->product_id) {
  1282. case USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT:
  1283. ctx->m_eControllerType = k_eSwitchDeviceInfoControllerType_JoyConLeft;
  1284. HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)");
  1285. device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
  1286. break;
  1287. case USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT:
  1288. ctx->m_eControllerType = k_eSwitchDeviceInfoControllerType_JoyConRight;
  1289. HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)");
  1290. device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
  1291. break;
  1292. case USB_PRODUCT_NINTENDO_SWITCH_PRO:
  1293. ctx->m_eControllerType = k_eSwitchDeviceInfoControllerType_ProController;
  1294. HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
  1295. device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
  1296. break;
  1297. default:
  1298. break;
  1299. }
  1300. }
  1301. return;
  1302. default:
  1303. device->type = SDL_GAMEPAD_TYPE_STANDARD;
  1304. break;
  1305. }
  1306. device->guid.data[15] = ctx->m_eControllerType;
  1307. (void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
  1308. ctx->m_rgucMACAddress[0],
  1309. ctx->m_rgucMACAddress[1],
  1310. ctx->m_rgucMACAddress[2],
  1311. ctx->m_rgucMACAddress[3],
  1312. ctx->m_rgucMACAddress[4],
  1313. ctx->m_rgucMACAddress[5]);
  1314. HIDAPI_SetDeviceSerial(device, serial);
  1315. }
  1316. }
  1317. static bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
  1318. {
  1319. SDL_DriverSwitch_Context *ctx;
  1320. ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx));
  1321. if (!ctx) {
  1322. return false;
  1323. }
  1324. ctx->device = device;
  1325. device->context = ctx;
  1326. ctx->m_nMaxWriteAttempts = GetMaxWriteAttempts(device);
  1327. ctx->m_bSyncWrite = true;
  1328. // Find out whether or not we can send output reports
  1329. ctx->m_bInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(device->vendor_id, device->product_id);
  1330. if (!ctx->m_bInputOnly) {
  1331. // Initialize rumble data, important for reading device info on the MOBAPAD M073
  1332. SetNeutralRumble(device, &ctx->m_RumblePacket.rumbleData[0]);
  1333. SetNeutralRumble(device, &ctx->m_RumblePacket.rumbleData[1]);
  1334. BReadDeviceInfo(ctx);
  1335. }
  1336. UpdateDeviceIdentity(device);
  1337. // Prefer the USB device over the Bluetooth device
  1338. if (device->is_bluetooth) {
  1339. if (HIDAPI_HasConnectedUSBDevice(device->serial)) {
  1340. return true;
  1341. }
  1342. } else {
  1343. HIDAPI_DisconnectBluetoothDevice(device->serial);
  1344. }
  1345. return HIDAPI_JoystickConnected(device, NULL);
  1346. }
  1347. static int HIDAPI_DriverSwitch_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
  1348. {
  1349. return -1;
  1350. }
  1351. static void HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
  1352. {
  1353. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1354. if (!ctx->joystick) {
  1355. return;
  1356. }
  1357. ctx->m_nPlayerIndex = player_index;
  1358. UpdateSlotLED(ctx);
  1359. }
  1360. static bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  1361. {
  1362. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1363. SDL_AssertJoysticksLocked();
  1364. ctx->joystick = joystick;
  1365. ctx->m_bSyncWrite = true;
  1366. if (!ctx->m_bInputOnly) {
  1367. #ifdef SDL_PLATFORM_MACOS
  1368. // Wait for the OS to finish its handshake with the controller
  1369. SDL_Delay(250);
  1370. #endif
  1371. GetInitialInputMode(ctx);
  1372. ctx->m_nCurrentInputMode = ctx->m_nInitialInputMode;
  1373. // Initialize rumble data
  1374. SetNeutralRumble(device, &ctx->m_RumblePacket.rumbleData[0]);
  1375. SetNeutralRumble(device, &ctx->m_RumblePacket.rumbleData[1]);
  1376. if (!device->is_bluetooth) {
  1377. if (!BTrySetupUSB(ctx)) {
  1378. SDL_SetError("Couldn't setup USB mode");
  1379. return false;
  1380. }
  1381. }
  1382. if (!LoadStickCalibration(ctx)) {
  1383. SDL_SetError("Couldn't load stick calibration");
  1384. return false;
  1385. }
  1386. if (ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_HVCLeft &&
  1387. ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_HVCRight &&
  1388. ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_NESLeft &&
  1389. ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_NESRight &&
  1390. ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_SNES &&
  1391. ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_N64 &&
  1392. ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_SEGA_Genesis &&
  1393. !(device->vendor_id == USB_VENDOR_PDP && device->product_id == USB_PRODUCT_PDP_REALMZ_WIRELESS)) {
  1394. if (LoadIMUCalibration(ctx)) {
  1395. ctx->m_bSensorsSupported = true;
  1396. }
  1397. }
  1398. // Enable vibration
  1399. SetVibrationEnabled(ctx, 1);
  1400. // Set desired input mode
  1401. SDL_AddHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
  1402. SDL_EnhancedReportsChanged, ctx);
  1403. // Start sending USB reports
  1404. if (!device->is_bluetooth) {
  1405. // ForceUSB doesn't generate an ACK, so don't wait for a reply
  1406. if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, false)) {
  1407. SDL_SetError("Couldn't start USB reports");
  1408. return false;
  1409. }
  1410. }
  1411. // Set the LED state
  1412. if (HasHomeLED(ctx)) {
  1413. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
  1414. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  1415. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED,
  1416. SDL_HomeLEDHintChanged, ctx);
  1417. } else {
  1418. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED,
  1419. SDL_HomeLEDHintChanged, ctx);
  1420. }
  1421. }
  1422. }
  1423. if (AlwaysUsesLabels(device->vendor_id, device->product_id, ctx->m_eControllerType)) {
  1424. ctx->m_bUseButtonLabels = true;
  1425. }
  1426. // Initialize player index (needed for setting LEDs)
  1427. ctx->m_nPlayerIndex = SDL_GetJoystickPlayerIndex(joystick);
  1428. ctx->m_bPlayerLights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, true);
  1429. UpdateSlotLED(ctx);
  1430. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED,
  1431. SDL_PlayerLEDHintChanged, ctx);
  1432. // Initialize the joystick capabilities
  1433. joystick->nbuttons = SDL_GAMEPAD_NUM_SWITCH_BUTTONS;
  1434. joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
  1435. joystick->nhats = 1;
  1436. // Set up for input
  1437. ctx->m_bSyncWrite = false;
  1438. ctx->m_ulLastIMUReset = ctx->m_ulLastInput = SDL_GetTicks();
  1439. ctx->m_ulIMUUpdateIntervalNS = SDL_MS_TO_NS(5); // Start off at 5 ms update rate
  1440. // Set up for vertical mode
  1441. ctx->m_bVerticalMode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, false);
  1442. return true;
  1443. }
  1444. static bool HIDAPI_DriverSwitch_ActuallyRumbleJoystick(SDL_DriverSwitch_Context *ctx, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  1445. {
  1446. /* Experimentally determined rumble values. These will only matter on some controllers as tested ones
  1447. * seem to disregard these and just use any non-zero rumble values as a binary flag for constant rumble
  1448. *
  1449. * More information about these values can be found here:
  1450. * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
  1451. */
  1452. const Uint16 k_usHighFreq = 0x0074;
  1453. const Uint8 k_ucHighFreqAmp = EncodeRumbleHighAmplitude(high_frequency_rumble);
  1454. const Uint8 k_ucLowFreq = 0x3D;
  1455. const Uint16 k_usLowFreqAmp = EncodeRumbleLowAmplitude(low_frequency_rumble);
  1456. if (low_frequency_rumble || high_frequency_rumble) {
  1457. EncodeRumble(ctx->device, &ctx->m_RumblePacket.rumbleData[0], k_usHighFreq, k_ucHighFreqAmp, k_ucLowFreq, k_usLowFreqAmp);
  1458. EncodeRumble(ctx->device, &ctx->m_RumblePacket.rumbleData[1], k_usHighFreq, k_ucHighFreqAmp, k_ucLowFreq, k_usLowFreqAmp);
  1459. } else {
  1460. SetNeutralRumble(ctx->device, &ctx->m_RumblePacket.rumbleData[0]);
  1461. SetNeutralRumble(ctx->device, &ctx->m_RumblePacket.rumbleData[1]);
  1462. }
  1463. ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble);
  1464. if (!WriteRumble(ctx)) {
  1465. return SDL_SetError("Couldn't send rumble packet");
  1466. }
  1467. return true;
  1468. }
  1469. static bool HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx)
  1470. {
  1471. if (SDL_GetTicks() < (ctx->m_ulRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) {
  1472. return true;
  1473. }
  1474. if (ctx->m_bRumblePending) {
  1475. Uint16 low_frequency_rumble = (Uint16)(ctx->m_unRumblePending >> 16);
  1476. Uint16 high_frequency_rumble = (Uint16)ctx->m_unRumblePending;
  1477. #ifdef DEBUG_RUMBLE
  1478. SDL_Log("Sent pending rumble %d/%d, %d ms after previous rumble", low_frequency_rumble, high_frequency_rumble, SDL_GetTicks() - ctx->m_ulRumbleSent);
  1479. #endif
  1480. ctx->m_bRumblePending = false;
  1481. ctx->m_unRumblePending = 0;
  1482. return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, low_frequency_rumble, high_frequency_rumble);
  1483. }
  1484. if (ctx->m_bRumbleZeroPending) {
  1485. ctx->m_bRumbleZeroPending = false;
  1486. #ifdef DEBUG_RUMBLE
  1487. SDL_Log("Sent pending zero rumble, %d ms after previous rumble", SDL_GetTicks() - ctx->m_ulRumbleSent);
  1488. #endif
  1489. return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, 0, 0);
  1490. }
  1491. return true;
  1492. }
  1493. static bool HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  1494. {
  1495. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1496. if (ctx->m_bInputOnly) {
  1497. return SDL_Unsupported();
  1498. }
  1499. if (device->parent) {
  1500. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
  1501. // Just handle low frequency rumble
  1502. high_frequency_rumble = 0;
  1503. } else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  1504. // Just handle high frequency rumble
  1505. low_frequency_rumble = 0;
  1506. }
  1507. }
  1508. if (ctx->m_bRumblePending) {
  1509. if (!HIDAPI_DriverSwitch_SendPendingRumble(ctx)) {
  1510. return false;
  1511. }
  1512. }
  1513. if (SDL_GetTicks() < (ctx->m_ulRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) {
  1514. if (low_frequency_rumble || high_frequency_rumble) {
  1515. Uint32 unRumblePending = ((Uint32)low_frequency_rumble << 16) | high_frequency_rumble;
  1516. // Keep the highest rumble intensity in the given interval
  1517. if (unRumblePending > ctx->m_unRumblePending) {
  1518. ctx->m_unRumblePending = unRumblePending;
  1519. }
  1520. ctx->m_bRumblePending = true;
  1521. ctx->m_bRumbleZeroPending = false;
  1522. } else {
  1523. // When rumble is complete, turn it off
  1524. ctx->m_bRumbleZeroPending = true;
  1525. }
  1526. return true;
  1527. }
  1528. #ifdef DEBUG_RUMBLE
  1529. SDL_Log("Sent rumble %d/%d", low_frequency_rumble, high_frequency_rumble);
  1530. #endif
  1531. return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, low_frequency_rumble, high_frequency_rumble);
  1532. }
  1533. static bool HIDAPI_DriverSwitch_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
  1534. {
  1535. return SDL_Unsupported();
  1536. }
  1537. static Uint32 HIDAPI_DriverSwitch_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  1538. {
  1539. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1540. Uint32 result = 0;
  1541. if (ctx->m_bPlayerLights && !ctx->m_bInputOnly) {
  1542. result |= SDL_JOYSTICK_CAP_PLAYER_LED;
  1543. }
  1544. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_ProController && !ctx->m_bInputOnly) {
  1545. // Doesn't have an RGB LED, so don't return SDL_JOYSTICK_CAP_RGB_LED here
  1546. result |= SDL_JOYSTICK_CAP_RUMBLE;
  1547. // But has the HOME LED, so treat it like a mono LED
  1548. result |= SDL_JOYSTICK_CAP_MONO_LED;
  1549. } else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
  1550. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  1551. result |= SDL_JOYSTICK_CAP_RUMBLE;
  1552. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  1553. result |= SDL_JOYSTICK_CAP_MONO_LED; // Right JoyCon also have the HOME LED
  1554. }
  1555. }
  1556. return result;
  1557. }
  1558. static bool HIDAPI_DriverSwitch_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
  1559. {
  1560. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1561. if (!(ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_ProController && !ctx->m_bInputOnly) &&
  1562. ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_JoyConRight) {
  1563. return SDL_Unsupported();
  1564. }
  1565. int value = (int)((SDL_max(red, SDL_max(green, blue)) / 255.0f) * 100.0f); // The colors are received between 0-255 and we need them to be 0-100
  1566. return SetHomeLED(ctx, (Uint8)value);
  1567. }
  1568. static bool HIDAPI_DriverSwitch_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
  1569. {
  1570. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1571. if (size == sizeof(SwitchCommonOutputPacket_t)) {
  1572. const SwitchCommonOutputPacket_t *packet = (SwitchCommonOutputPacket_t *)data;
  1573. if (packet->ucPacketType != k_eSwitchOutputReportIDs_Rumble) {
  1574. return SDL_SetError("Unknown Nintendo Switch Pro effect type");
  1575. }
  1576. SDL_copyp(&ctx->m_RumblePacket.rumbleData[0], &packet->rumbleData[0]);
  1577. SDL_copyp(&ctx->m_RumblePacket.rumbleData[1], &packet->rumbleData[1]);
  1578. if (!WriteRumble(ctx)) {
  1579. return false;
  1580. }
  1581. // This overwrites any internal rumble
  1582. ctx->m_bRumblePending = false;
  1583. ctx->m_bRumbleZeroPending = false;
  1584. return true;
  1585. } else if (size >= 2 && size <= 256) {
  1586. const Uint8 *payload = (const Uint8 *)data;
  1587. ESwitchSubcommandIDs cmd = (ESwitchSubcommandIDs)payload[0];
  1588. if (cmd == k_eSwitchSubcommandIDs_SetInputReportMode && !device->is_bluetooth) {
  1589. // Going into simple mode over USB disables input reports, so don't do that
  1590. return true;
  1591. }
  1592. if (cmd == k_eSwitchSubcommandIDs_SetHomeLight && !HasHomeLED(ctx)) {
  1593. // Setting the home LED when it's not supported can cause the controller to reset
  1594. return true;
  1595. }
  1596. if (!WriteSubcommand(ctx, cmd, &payload[1], (Uint8)(size - 1), NULL)) {
  1597. return false;
  1598. }
  1599. return true;
  1600. }
  1601. return SDL_Unsupported();
  1602. }
  1603. static bool HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
  1604. {
  1605. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  1606. UpdateEnhancedModeOnApplicationUsage(ctx);
  1607. if (!ctx->m_bSensorsSupported || (enabled && !ctx->m_bEnhancedMode)) {
  1608. return SDL_Unsupported();
  1609. }
  1610. ctx->m_bReportSensors = enabled;
  1611. ctx->m_unIMUSamples = 0;
  1612. ctx->m_ulIMUSampleTimestampNS = SDL_GetTicksNS();
  1613. UpdateInputMode(ctx);
  1614. SetIMUEnabled(ctx, enabled);
  1615. return true;
  1616. }
  1617. static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet)
  1618. {
  1619. Sint16 axis;
  1620. Uint64 timestamp = SDL_GetTicksNS();
  1621. if (packet->rgucButtons[0] != ctx->m_lastInputOnlyState.rgucButtons[0]) {
  1622. Uint8 data = packet->rgucButtons[0];
  1623. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x02) != 0));
  1624. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x04) != 0));
  1625. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x01) != 0));
  1626. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x08) != 0));
  1627. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x10) != 0));
  1628. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x20) != 0));
  1629. }
  1630. if (packet->rgucButtons[1] != ctx->m_lastInputOnlyState.rgucButtons[1]) {
  1631. Uint8 data = packet->rgucButtons[1];
  1632. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data & 0x01) != 0));
  1633. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x02) != 0));
  1634. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x04) != 0));
  1635. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data & 0x08) != 0));
  1636. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x10) != 0));
  1637. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, ((data & 0x20) != 0));
  1638. }
  1639. if (packet->ucStickHat != ctx->m_lastInputOnlyState.ucStickHat) {
  1640. Uint8 hat;
  1641. switch (packet->ucStickHat) {
  1642. case 0:
  1643. hat = SDL_HAT_UP;
  1644. break;
  1645. case 1:
  1646. hat = SDL_HAT_RIGHTUP;
  1647. break;
  1648. case 2:
  1649. hat = SDL_HAT_RIGHT;
  1650. break;
  1651. case 3:
  1652. hat = SDL_HAT_RIGHTDOWN;
  1653. break;
  1654. case 4:
  1655. hat = SDL_HAT_DOWN;
  1656. break;
  1657. case 5:
  1658. hat = SDL_HAT_LEFTDOWN;
  1659. break;
  1660. case 6:
  1661. hat = SDL_HAT_LEFT;
  1662. break;
  1663. case 7:
  1664. hat = SDL_HAT_LEFTUP;
  1665. break;
  1666. default:
  1667. hat = SDL_HAT_CENTERED;
  1668. break;
  1669. }
  1670. SDL_SendJoystickHat(timestamp, joystick, 0, hat);
  1671. }
  1672. axis = (packet->rgucButtons[0] & 0x40) ? 32767 : -32768;
  1673. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
  1674. axis = (packet->rgucButtons[0] & 0x80) ? 32767 : -32768;
  1675. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
  1676. if (packet->rgucJoystickLeft[0] != ctx->m_lastInputOnlyState.rgucJoystickLeft[0]) {
  1677. axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickLeft[0], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
  1678. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
  1679. }
  1680. if (packet->rgucJoystickLeft[1] != ctx->m_lastInputOnlyState.rgucJoystickLeft[1]) {
  1681. axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickLeft[1], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
  1682. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
  1683. }
  1684. if (packet->rgucJoystickRight[0] != ctx->m_lastInputOnlyState.rgucJoystickRight[0]) {
  1685. axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickRight[0], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
  1686. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
  1687. }
  1688. if (packet->rgucJoystickRight[1] != ctx->m_lastInputOnlyState.rgucJoystickRight[1]) {
  1689. axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickRight[1], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
  1690. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
  1691. }
  1692. ctx->m_lastInputOnlyState = *packet;
  1693. }
  1694. static void HandleCombinedSimpleControllerStateL(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchSimpleStatePacket_t *packet)
  1695. {
  1696. if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
  1697. Uint8 data = packet->rgucButtons[0];
  1698. Uint8 hat = 0;
  1699. if (data & 0x01) {
  1700. hat |= SDL_HAT_LEFT;
  1701. }
  1702. if (data & 0x02) {
  1703. hat |= SDL_HAT_DOWN;
  1704. }
  1705. if (data & 0x04) {
  1706. hat |= SDL_HAT_UP;
  1707. }
  1708. if (data & 0x08) {
  1709. hat |= SDL_HAT_RIGHT;
  1710. }
  1711. SDL_SendJoystickHat(timestamp, joystick, 0, hat);
  1712. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, ((data & 0x10) != 0));
  1713. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, ((data & 0x20) != 0));
  1714. }
  1715. if (packet->rgucButtons[1] != ctx->m_lastSimpleState.rgucButtons[1]) {
  1716. Uint8 data = packet->rgucButtons[1];
  1717. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data & 0x01) != 0));
  1718. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x04) != 0));
  1719. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, ((data & 0x20) != 0));
  1720. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x40) != 0));
  1721. }
  1722. Sint16 axis = (packet->rgucButtons[1] & 0x80) ? 32767 : -32768;
  1723. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
  1724. if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
  1725. switch (packet->ucStickHat) {
  1726. case 0:
  1727. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1728. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1729. break;
  1730. case 1:
  1731. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1732. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1733. break;
  1734. case 2:
  1735. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1736. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1737. break;
  1738. case 3:
  1739. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1740. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1741. break;
  1742. case 4:
  1743. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1744. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1745. break;
  1746. case 5:
  1747. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1748. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1749. break;
  1750. case 6:
  1751. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1752. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1753. break;
  1754. case 7:
  1755. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1756. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1757. break;
  1758. default:
  1759. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1760. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1761. break;
  1762. }
  1763. }
  1764. }
  1765. static void HandleCombinedSimpleControllerStateR(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchSimpleStatePacket_t *packet)
  1766. {
  1767. if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
  1768. Uint8 data = packet->rgucButtons[0];
  1769. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x01) != 0));
  1770. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x02) != 0));
  1771. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x04) != 0));
  1772. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x08) != 0));
  1773. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, ((data & 0x10) != 0));
  1774. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, ((data & 0x20) != 0));
  1775. }
  1776. if (packet->rgucButtons[1] != ctx->m_lastSimpleState.rgucButtons[1]) {
  1777. Uint8 data = packet->rgucButtons[1];
  1778. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x02) != 0));
  1779. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data & 0x08) != 0));
  1780. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x10) != 0));
  1781. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x40) != 0));
  1782. }
  1783. Sint16 axis = (packet->rgucButtons[1] & 0x80) ? 32767 : -32768;
  1784. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
  1785. if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
  1786. switch (packet->ucStickHat) {
  1787. case 0:
  1788. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_JOYSTICK_AXIS_MIN);
  1789. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, 0);
  1790. break;
  1791. case 1:
  1792. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_JOYSTICK_AXIS_MIN);
  1793. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_JOYSTICK_AXIS_MIN);
  1794. break;
  1795. case 2:
  1796. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, 0);
  1797. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_JOYSTICK_AXIS_MIN);
  1798. break;
  1799. case 3:
  1800. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_JOYSTICK_AXIS_MAX);
  1801. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_JOYSTICK_AXIS_MIN);
  1802. break;
  1803. case 4:
  1804. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_JOYSTICK_AXIS_MAX);
  1805. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, 0);
  1806. break;
  1807. case 5:
  1808. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_JOYSTICK_AXIS_MAX);
  1809. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_JOYSTICK_AXIS_MAX);
  1810. break;
  1811. case 6:
  1812. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, 0);
  1813. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_JOYSTICK_AXIS_MAX);
  1814. break;
  1815. case 7:
  1816. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, SDL_JOYSTICK_AXIS_MIN);
  1817. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, SDL_JOYSTICK_AXIS_MAX);
  1818. break;
  1819. default:
  1820. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, 0);
  1821. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, 0);
  1822. break;
  1823. }
  1824. }
  1825. }
  1826. static void HandleMiniSimpleControllerStateL(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchSimpleStatePacket_t *packet)
  1827. {
  1828. if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
  1829. Uint8 data = packet->rgucButtons[0];
  1830. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x01) != 0));
  1831. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x02) != 0));
  1832. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x04) != 0));
  1833. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x08) != 0));
  1834. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x10) != 0));
  1835. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x20) != 0));
  1836. }
  1837. if (packet->rgucButtons[1] != ctx->m_lastSimpleState.rgucButtons[1]) {
  1838. Uint8 data = packet->rgucButtons[1];
  1839. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x01) != 0));
  1840. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x04) != 0));
  1841. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x20) != 0));
  1842. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, ((data & 0x40) != 0));
  1843. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, ((data & 0x80) != 0));
  1844. }
  1845. if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
  1846. switch (packet->ucStickHat) {
  1847. case 0:
  1848. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1849. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1850. break;
  1851. case 1:
  1852. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1853. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1854. break;
  1855. case 2:
  1856. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1857. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1858. break;
  1859. case 3:
  1860. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1861. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1862. break;
  1863. case 4:
  1864. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1865. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1866. break;
  1867. case 5:
  1868. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1869. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1870. break;
  1871. case 6:
  1872. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1873. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1874. break;
  1875. case 7:
  1876. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1877. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1878. break;
  1879. default:
  1880. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1881. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1882. break;
  1883. }
  1884. }
  1885. }
  1886. static void HandleMiniSimpleControllerStateR(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchSimpleStatePacket_t *packet)
  1887. {
  1888. if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
  1889. Uint8 data = packet->rgucButtons[0];
  1890. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x01) != 0));
  1891. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x02) != 0));
  1892. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x04) != 0));
  1893. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x08) != 0));
  1894. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x10) != 0));
  1895. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x20) != 0));
  1896. }
  1897. if (packet->rgucButtons[1] != ctx->m_lastSimpleState.rgucButtons[1]) {
  1898. Uint8 data = packet->rgucButtons[1];
  1899. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x02) != 0));
  1900. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x08) != 0));
  1901. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x10) != 0));
  1902. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, ((data & 0x20) != 0));
  1903. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, ((data & 0x40) != 0));
  1904. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, ((data & 0x80) != 0));
  1905. }
  1906. if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
  1907. switch (packet->ucStickHat) {
  1908. case 0:
  1909. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1910. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1911. break;
  1912. case 1:
  1913. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1914. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1915. break;
  1916. case 2:
  1917. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1918. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1919. break;
  1920. case 3:
  1921. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MAX);
  1922. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1923. break;
  1924. case 4:
  1925. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1926. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1927. break;
  1928. case 5:
  1929. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1930. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MAX);
  1931. break;
  1932. case 6:
  1933. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1934. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1935. break;
  1936. case 7:
  1937. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_JOYSTICK_AXIS_MIN);
  1938. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, SDL_JOYSTICK_AXIS_MIN);
  1939. break;
  1940. default:
  1941. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, 0);
  1942. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, 0);
  1943. break;
  1944. }
  1945. }
  1946. }
  1947. static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchSimpleStatePacket_t *packet)
  1948. {
  1949. Uint64 timestamp = SDL_GetTicksNS();
  1950. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
  1951. if (ctx->device->parent || ctx->m_bVerticalMode) {
  1952. HandleCombinedSimpleControllerStateL(timestamp, joystick, ctx, packet);
  1953. } else {
  1954. HandleMiniSimpleControllerStateL(timestamp, joystick, ctx, packet);
  1955. }
  1956. } else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  1957. if (ctx->device->parent || ctx->m_bVerticalMode) {
  1958. HandleCombinedSimpleControllerStateR(timestamp, joystick, ctx, packet);
  1959. } else {
  1960. HandleMiniSimpleControllerStateR(timestamp, joystick, ctx, packet);
  1961. }
  1962. } else {
  1963. Sint16 axis;
  1964. if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
  1965. Uint8 data = packet->rgucButtons[0];
  1966. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x01) != 0));
  1967. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x02) != 0));
  1968. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x04) != 0));
  1969. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x08) != 0));
  1970. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x10) != 0));
  1971. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x20) != 0));
  1972. }
  1973. if (packet->rgucButtons[1] != ctx->m_lastSimpleState.rgucButtons[1]) {
  1974. Uint8 data = packet->rgucButtons[1];
  1975. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data & 0x01) != 0));
  1976. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x02) != 0));
  1977. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x04) != 0));
  1978. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data & 0x08) != 0));
  1979. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x10) != 0));
  1980. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, ((data & 0x20) != 0));
  1981. }
  1982. if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
  1983. Uint8 hat;
  1984. switch (packet->ucStickHat) {
  1985. case 0:
  1986. hat = SDL_HAT_UP;
  1987. break;
  1988. case 1:
  1989. hat = SDL_HAT_RIGHTUP;
  1990. break;
  1991. case 2:
  1992. hat = SDL_HAT_RIGHT;
  1993. break;
  1994. case 3:
  1995. hat = SDL_HAT_RIGHTDOWN;
  1996. break;
  1997. case 4:
  1998. hat = SDL_HAT_DOWN;
  1999. break;
  2000. case 5:
  2001. hat = SDL_HAT_LEFTDOWN;
  2002. break;
  2003. case 6:
  2004. hat = SDL_HAT_LEFT;
  2005. break;
  2006. case 7:
  2007. hat = SDL_HAT_LEFTUP;
  2008. break;
  2009. default:
  2010. hat = SDL_HAT_CENTERED;
  2011. break;
  2012. }
  2013. SDL_SendJoystickHat(timestamp, joystick, 0, hat);
  2014. }
  2015. axis = (packet->rgucButtons[0] & 0x40) ? 32767 : -32768;
  2016. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
  2017. axis = ((packet->rgucButtons[0] & 0x80) || (packet->rgucButtons[1] & 0x80)) ? 32767 : -32768;
  2018. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
  2019. axis = ApplySimpleStickCalibration(ctx, 0, 0, packet->sJoystickLeft[0]);
  2020. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
  2021. axis = ApplySimpleStickCalibration(ctx, 0, 1, packet->sJoystickLeft[1]);
  2022. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
  2023. axis = ApplySimpleStickCalibration(ctx, 1, 0, packet->sJoystickRight[0]);
  2024. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
  2025. axis = ApplySimpleStickCalibration(ctx, 1, 1, packet->sJoystickRight[1]);
  2026. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
  2027. }
  2028. ctx->m_lastSimpleState = *packet;
  2029. }
  2030. static void SendSensorUpdate(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SDL_SensorType type, Uint64 sensor_timestamp, const Sint16 *values)
  2031. {
  2032. float data[3];
  2033. /* Note the order of components has been shuffled to match PlayStation controllers,
  2034. * since that's our de facto standard from already supporting those controllers, and
  2035. * users will want consistent axis mappings across devices.
  2036. */
  2037. if (type == SDL_SENSOR_GYRO || type == SDL_SENSOR_GYRO_L || type == SDL_SENSOR_GYRO_R) {
  2038. data[0] = -(ctx->m_IMUScaleData.fGyroScaleY * (float)values[1]);
  2039. data[1] = ctx->m_IMUScaleData.fGyroScaleZ * (float)values[2];
  2040. data[2] = -(ctx->m_IMUScaleData.fGyroScaleX * (float)values[0]);
  2041. } else {
  2042. data[0] = -(ctx->m_IMUScaleData.fAccelScaleY * (float)values[1]);
  2043. data[1] = ctx->m_IMUScaleData.fAccelScaleZ * (float)values[2];
  2044. data[2] = -(ctx->m_IMUScaleData.fAccelScaleX * (float)values[0]);
  2045. }
  2046. // Right Joy-Con flips some axes, so let's flip them back for consistency
  2047. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  2048. data[0] = -data[0];
  2049. data[1] = -data[1];
  2050. }
  2051. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft &&
  2052. !ctx->device->parent && !ctx->m_bVerticalMode) {
  2053. // Mini-gamepad mode, swap some axes around
  2054. float tmp = data[2];
  2055. data[2] = -data[0];
  2056. data[0] = tmp;
  2057. }
  2058. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight &&
  2059. !ctx->device->parent && !ctx->m_bVerticalMode) {
  2060. // Mini-gamepad mode, swap some axes around
  2061. float tmp = data[2];
  2062. data[2] = data[0];
  2063. data[0] = -tmp;
  2064. }
  2065. SDL_SendJoystickSensor(timestamp, joystick, type, sensor_timestamp, data, 3);
  2066. }
  2067. static void HandleCombinedControllerStateL(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
  2068. {
  2069. Sint16 axis;
  2070. if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
  2071. Uint8 data = packet->controllerState.rgucButtons[1];
  2072. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data & 0x01) != 0));
  2073. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x08) != 0));
  2074. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, ((data & 0x20) != 0));
  2075. }
  2076. if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
  2077. Uint8 data = packet->controllerState.rgucButtons[2];
  2078. Uint8 hat = 0;
  2079. if (data & 0x01) {
  2080. hat |= SDL_HAT_DOWN;
  2081. }
  2082. if (data & 0x02) {
  2083. hat |= SDL_HAT_UP;
  2084. }
  2085. if (data & 0x04) {
  2086. hat |= SDL_HAT_RIGHT;
  2087. }
  2088. if (data & 0x08) {
  2089. hat |= SDL_HAT_LEFT;
  2090. }
  2091. SDL_SendJoystickHat(timestamp, joystick, 0, hat);
  2092. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, ((data & 0x10) != 0));
  2093. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, ((data & 0x20) != 0));
  2094. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x40) != 0));
  2095. axis = (data & 0x80) ? 32767 : -32768;
  2096. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
  2097. }
  2098. axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
  2099. axis = ApplyStickCalibration(ctx, 0, 0, axis);
  2100. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
  2101. axis = ((packet->controllerState.rgucJoystickLeft[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickLeft[2] << 4);
  2102. axis = ApplyStickCalibration(ctx, 0, 1, axis);
  2103. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, ~axis);
  2104. }
  2105. static void HandleCombinedControllerStateR(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
  2106. {
  2107. Sint16 axis;
  2108. if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
  2109. Uint8 data = packet->controllerState.rgucButtons[0];
  2110. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x04) != 0));
  2111. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x08) != 0));
  2112. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x01) != 0));
  2113. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x02) != 0));
  2114. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, ((data & 0x10) != 0));
  2115. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, ((data & 0x20) != 0));
  2116. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x40) != 0));
  2117. axis = (data & 0x80) ? 32767 : -32768;
  2118. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
  2119. }
  2120. if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
  2121. Uint8 data = packet->controllerState.rgucButtons[1];
  2122. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x02) != 0));
  2123. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data & 0x04) != 0));
  2124. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x10) != 0));
  2125. }
  2126. axis = packet->controllerState.rgucJoystickRight[0] | ((packet->controllerState.rgucJoystickRight[1] & 0xF) << 8);
  2127. axis = ApplyStickCalibration(ctx, 1, 0, axis);
  2128. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
  2129. axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
  2130. axis = ApplyStickCalibration(ctx, 1, 1, axis);
  2131. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, ~axis);
  2132. }
  2133. static void HandleMiniControllerStateL(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
  2134. {
  2135. Sint16 axis;
  2136. if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
  2137. Uint8 data = packet->controllerState.rgucButtons[1];
  2138. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x01) != 0));
  2139. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x08) != 0));
  2140. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x20) != 0));
  2141. }
  2142. if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
  2143. Uint8 data = packet->controllerState.rgucButtons[2];
  2144. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x08) != 0));
  2145. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x01) != 0));
  2146. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x02) != 0));
  2147. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x04) != 0));
  2148. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x10) != 0));
  2149. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x20) != 0));
  2150. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, ((data & 0x40) != 0));
  2151. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, ((data & 0x80) != 0));
  2152. }
  2153. axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
  2154. axis = ApplyStickCalibration(ctx, 0, 0, axis);
  2155. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, ~axis);
  2156. axis = ((packet->controllerState.rgucJoystickLeft[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickLeft[2] << 4);
  2157. axis = ApplyStickCalibration(ctx, 0, 1, axis);
  2158. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, ~axis);
  2159. }
  2160. static void HandleMiniControllerStateR(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
  2161. {
  2162. Sint16 axis;
  2163. if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
  2164. Uint8 data = packet->controllerState.rgucButtons[0];
  2165. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x08) != 0));
  2166. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x02) != 0));
  2167. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x04) != 0));
  2168. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x01) != 0));
  2169. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x10) != 0));
  2170. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x20) != 0));
  2171. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, ((data & 0x40) != 0));
  2172. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, ((data & 0x80) != 0));
  2173. }
  2174. if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
  2175. Uint8 data = packet->controllerState.rgucButtons[1];
  2176. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x02) != 0));
  2177. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x04) != 0));
  2178. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x10) != 0));
  2179. }
  2180. axis = packet->controllerState.rgucJoystickRight[0] | ((packet->controllerState.rgucJoystickRight[1] & 0xF) << 8);
  2181. axis = ApplyStickCalibration(ctx, 1, 0, axis);
  2182. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
  2183. axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
  2184. axis = ApplyStickCalibration(ctx, 1, 1, axis);
  2185. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
  2186. }
  2187. static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet) SDL_NO_THREAD_SAFETY_ANALYSIS // We unlock and lock the device lock to be able to change IMU state
  2188. {
  2189. Uint64 timestamp = SDL_GetTicksNS();
  2190. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
  2191. if (ctx->device->parent || ctx->m_bVerticalMode) {
  2192. HandleCombinedControllerStateL(timestamp, joystick, ctx, packet);
  2193. } else {
  2194. HandleMiniControllerStateL(timestamp, joystick, ctx, packet);
  2195. }
  2196. } else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  2197. if (ctx->device->parent || ctx->m_bVerticalMode) {
  2198. HandleCombinedControllerStateR(timestamp, joystick, ctx, packet);
  2199. } else {
  2200. HandleMiniControllerStateR(timestamp, joystick, ctx, packet);
  2201. }
  2202. } else {
  2203. Sint16 axis;
  2204. if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
  2205. Uint8 data = packet->controllerState.rgucButtons[0];
  2206. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), ((data & 0x04) != 0));
  2207. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), ((data & 0x08) != 0));
  2208. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), ((data & 0x01) != 0));
  2209. SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), ((data & 0x02) != 0));
  2210. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data & 0x40) != 0));
  2211. }
  2212. if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
  2213. Uint8 data = packet->controllerState.rgucButtons[1];
  2214. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data & 0x01) != 0));
  2215. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data & 0x02) != 0));
  2216. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data & 0x04) != 0));
  2217. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data & 0x08) != 0));
  2218. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data & 0x10) != 0));
  2219. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, ((data & 0x20) != 0));
  2220. }
  2221. if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
  2222. Uint8 data = packet->controllerState.rgucButtons[2];
  2223. Uint8 hat = 0;
  2224. if (data & 0x01) {
  2225. hat |= SDL_HAT_DOWN;
  2226. }
  2227. if (data & 0x02) {
  2228. hat |= SDL_HAT_UP;
  2229. }
  2230. if (data & 0x04) {
  2231. hat |= SDL_HAT_RIGHT;
  2232. }
  2233. if (data & 0x08) {
  2234. hat |= SDL_HAT_LEFT;
  2235. }
  2236. SDL_SendJoystickHat(timestamp, joystick, 0, hat);
  2237. SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data & 0x40) != 0));
  2238. }
  2239. axis = (packet->controllerState.rgucButtons[0] & 0x80) ? 32767 : -32768;
  2240. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
  2241. axis = (packet->controllerState.rgucButtons[2] & 0x80) ? 32767 : -32768;
  2242. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
  2243. axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
  2244. axis = ApplyStickCalibration(ctx, 0, 0, axis);
  2245. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
  2246. axis = ((packet->controllerState.rgucJoystickLeft[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickLeft[2] << 4);
  2247. axis = ApplyStickCalibration(ctx, 0, 1, axis);
  2248. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, ~axis);
  2249. axis = packet->controllerState.rgucJoystickRight[0] | ((packet->controllerState.rgucJoystickRight[1] & 0xF) << 8);
  2250. axis = ApplyStickCalibration(ctx, 1, 0, axis);
  2251. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
  2252. axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
  2253. axis = ApplyStickCalibration(ctx, 1, 1, axis);
  2254. SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, ~axis);
  2255. }
  2256. /* High nibble of battery/connection byte is battery level, low nibble is connection status (always 0 on 8BitDo Pro 2)
  2257. * LSB of connection nibble is USB/Switch connection status
  2258. * LSB of the battery nibble is used to report charging.
  2259. * The battery level is reported from 0(empty)-8(full)
  2260. */
  2261. int charging = (packet->controllerState.ucBatteryAndConnection & 0x10);
  2262. int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4;
  2263. if (charging) {
  2264. if (level == 8) {
  2265. ctx->m_ePowerState = SDL_POWERSTATE_CHARGED;
  2266. } else {
  2267. ctx->m_ePowerState = SDL_POWERSTATE_CHARGING;
  2268. }
  2269. } else {
  2270. ctx->m_ePowerState = SDL_POWERSTATE_ON_BATTERY;
  2271. }
  2272. ctx->m_nPowerPercent = (int)SDL_roundf((level / 8.0f) * 100.0f);
  2273. if (!ctx->device->parent) {
  2274. SDL_PowerState state = ctx->m_ePowerState;
  2275. int percent = ctx->m_nPowerPercent;
  2276. SDL_SendJoystickPowerInfo(joystick, state, percent);
  2277. } else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  2278. SDL_DriverSwitch_Context *other = (SDL_DriverSwitch_Context *)ctx->device->parent->children[0]->context;
  2279. SDL_PowerState state = (SDL_PowerState)SDL_min(ctx->m_ePowerState, other->m_ePowerState);
  2280. int percent = SDL_min(ctx->m_nPowerPercent, other->m_nPowerPercent);
  2281. SDL_SendJoystickPowerInfo(joystick, state, percent);
  2282. }
  2283. if (ctx->m_bReportSensors) {
  2284. // Need to copy the imuState to an aligned variable
  2285. SwitchControllerIMUState_t imuState[3];
  2286. SDL_COMPILE_TIME_ASSERT(imuState_size, sizeof(imuState) == sizeof(packet->imuState));
  2287. SDL_memcpy(imuState, packet->imuState, sizeof(packet->imuState));
  2288. bool bHasSensorData = (imuState[0].sAccelZ != 0 ||
  2289. imuState[0].sAccelY != 0 ||
  2290. imuState[0].sAccelX != 0);
  2291. if (bHasSensorData) {
  2292. const Uint32 IMU_UPDATE_RATE_SAMPLE_FREQUENCY = 1000;
  2293. Uint64 sensor_timestamp[3];
  2294. ctx->m_bHasSensorData = true;
  2295. // We got three IMU samples, calculate the IMU update rate and timestamps
  2296. ctx->m_unIMUSamples += 3;
  2297. if (ctx->m_unIMUSamples >= IMU_UPDATE_RATE_SAMPLE_FREQUENCY) {
  2298. Uint64 now = SDL_GetTicksNS();
  2299. Uint64 elapsed = (now - ctx->m_ulIMUSampleTimestampNS);
  2300. if (elapsed > 0) {
  2301. ctx->m_ulIMUUpdateIntervalNS = elapsed / ctx->m_unIMUSamples;
  2302. }
  2303. ctx->m_unIMUSamples = 0;
  2304. ctx->m_ulIMUSampleTimestampNS = now;
  2305. }
  2306. ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
  2307. sensor_timestamp[0] = ctx->m_ulTimestampNS;
  2308. ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
  2309. sensor_timestamp[1] = ctx->m_ulTimestampNS;
  2310. ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
  2311. sensor_timestamp[2] = ctx->m_ulTimestampNS;
  2312. if (!ctx->device->parent ||
  2313. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  2314. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[0], &imuState[2].sGyroX);
  2315. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[0], &imuState[2].sAccelX);
  2316. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[1], &imuState[1].sGyroX);
  2317. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[1], &imuState[1].sAccelX);
  2318. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[2], &imuState[0].sGyroX);
  2319. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[2], &imuState[0].sAccelX);
  2320. }
  2321. if (ctx->device->parent &&
  2322. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
  2323. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[0], &imuState[2].sGyroX);
  2324. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[0], &imuState[2].sAccelX);
  2325. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[1], &imuState[1].sGyroX);
  2326. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[1], &imuState[1].sAccelX);
  2327. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[2], &imuState[0].sGyroX);
  2328. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[2], &imuState[0].sAccelX);
  2329. }
  2330. if (ctx->device->parent &&
  2331. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  2332. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[0], &imuState[2].sGyroX);
  2333. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[0], &imuState[2].sAccelX);
  2334. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[1], &imuState[1].sGyroX);
  2335. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[1], &imuState[1].sAccelX);
  2336. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[2], &imuState[0].sGyroX);
  2337. SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[2], &imuState[0].sAccelX);
  2338. }
  2339. } else if (ctx->m_bHasSensorData) {
  2340. // Uh oh, someone turned off the IMU?
  2341. const int IMU_RESET_DELAY_MS = 3000;
  2342. Uint64 now = SDL_GetTicks();
  2343. if (now >= (ctx->m_ulLastIMUReset + IMU_RESET_DELAY_MS)) {
  2344. SDL_HIDAPI_Device *device = ctx->device;
  2345. if (device->updating) {
  2346. SDL_UnlockMutex(device->dev_lock);
  2347. }
  2348. SetIMUEnabled(ctx, true);
  2349. if (device->updating) {
  2350. SDL_LockMutex(device->dev_lock);
  2351. }
  2352. ctx->m_ulLastIMUReset = now;
  2353. }
  2354. } else {
  2355. // We have never gotten IMU data, probably not supported on this device
  2356. }
  2357. }
  2358. ctx->m_lastFullState = *packet;
  2359. }
  2360. static bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
  2361. {
  2362. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  2363. SDL_Joystick *joystick = NULL;
  2364. int size;
  2365. int packet_count = 0;
  2366. Uint64 now = SDL_GetTicks();
  2367. if (device->num_joysticks > 0) {
  2368. joystick = SDL_GetJoystickFromID(device->joysticks[0]);
  2369. }
  2370. while ((size = ReadInput(ctx)) > 0) {
  2371. #ifdef DEBUG_SWITCH_PROTOCOL
  2372. HIDAPI_DumpPacket("Nintendo Switch packet: size = %d", ctx->m_rgucReadBuffer, size);
  2373. #endif
  2374. ++packet_count;
  2375. ctx->m_ulLastInput = now;
  2376. if (!joystick) {
  2377. continue;
  2378. }
  2379. if (ctx->m_bInputOnly) {
  2380. HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]);
  2381. } else {
  2382. if (ctx->m_rgucReadBuffer[0] == k_eSwitchInputReportIDs_SubcommandReply) {
  2383. continue;
  2384. }
  2385. ctx->m_nCurrentInputMode = ctx->m_rgucReadBuffer[0];
  2386. switch (ctx->m_rgucReadBuffer[0]) {
  2387. case k_eSwitchInputReportIDs_SimpleControllerState:
  2388. HandleSimpleControllerState(joystick, ctx, (SwitchSimpleStatePacket_t *)&ctx->m_rgucReadBuffer[1]);
  2389. break;
  2390. case k_eSwitchInputReportIDs_FullControllerState:
  2391. case k_eSwitchInputReportIDs_FullControllerAndMcuState:
  2392. // This is the extended report, we can enable sensors now in auto mode
  2393. UpdateEnhancedModeOnEnhancedReport(ctx);
  2394. HandleFullControllerState(joystick, ctx, (SwitchStatePacket_t *)&ctx->m_rgucReadBuffer[1]);
  2395. break;
  2396. default:
  2397. break;
  2398. }
  2399. }
  2400. }
  2401. if (joystick) {
  2402. if (packet_count == 0) {
  2403. if (!ctx->m_bInputOnly && !device->is_bluetooth &&
  2404. ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
  2405. const int INPUT_WAIT_TIMEOUT_MS = 100;
  2406. if (now >= (ctx->m_ulLastInput + INPUT_WAIT_TIMEOUT_MS)) {
  2407. // Steam may have put the controller back into non-reporting mode
  2408. bool wasSyncWrite = ctx->m_bSyncWrite;
  2409. ctx->m_bSyncWrite = true;
  2410. WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, false);
  2411. ctx->m_bSyncWrite = wasSyncWrite;
  2412. }
  2413. } else if (device->is_bluetooth &&
  2414. ctx->m_nCurrentInputMode != k_eSwitchInputReportIDs_SimpleControllerState) {
  2415. const int INPUT_WAIT_TIMEOUT_MS = 3000;
  2416. if (now >= (ctx->m_ulLastInput + INPUT_WAIT_TIMEOUT_MS)) {
  2417. // Bluetooth may have disconnected, try reopening the controller
  2418. size = -1;
  2419. }
  2420. }
  2421. }
  2422. if (ctx->m_bRumblePending || ctx->m_bRumbleZeroPending) {
  2423. HIDAPI_DriverSwitch_SendPendingRumble(ctx);
  2424. } else if (ctx->m_bRumbleActive &&
  2425. now >= (ctx->m_ulRumbleSent + RUMBLE_REFRESH_FREQUENCY_MS)) {
  2426. #ifdef DEBUG_RUMBLE
  2427. SDL_Log("Sent continuing rumble, %d ms after previous rumble", now - ctx->m_ulRumbleSent);
  2428. #endif
  2429. WriteRumble(ctx);
  2430. }
  2431. }
  2432. // Reconnect the Bluetooth device once the USB device is gone
  2433. if (device->num_joysticks == 0 && device->is_bluetooth && packet_count > 0 &&
  2434. !device->parent &&
  2435. !HIDAPI_HasConnectedUSBDevice(device->serial)) {
  2436. HIDAPI_JoystickConnected(device, NULL);
  2437. }
  2438. if (size < 0 && device->num_joysticks > 0) {
  2439. // Read error, device is disconnected
  2440. HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
  2441. }
  2442. return (size >= 0);
  2443. }
  2444. static void HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  2445. {
  2446. SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
  2447. if (!ctx->m_bInputOnly) {
  2448. // Restore simple input mode for other applications
  2449. if (!ctx->m_nInitialInputMode ||
  2450. ctx->m_nInitialInputMode == k_eSwitchInputReportIDs_SimpleControllerState) {
  2451. SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
  2452. }
  2453. }
  2454. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
  2455. SDL_EnhancedReportsChanged, ctx);
  2456. if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
  2457. ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
  2458. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED,
  2459. SDL_HomeLEDHintChanged, ctx);
  2460. } else {
  2461. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED,
  2462. SDL_HomeLEDHintChanged, ctx);
  2463. }
  2464. SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED,
  2465. SDL_PlayerLEDHintChanged, ctx);
  2466. ctx->joystick = NULL;
  2467. ctx->m_bReportSensors = false;
  2468. ctx->m_bEnhancedMode = false;
  2469. ctx->m_bEnhancedModeAvailable = false;
  2470. }
  2471. static void HIDAPI_DriverSwitch_FreeDevice(SDL_HIDAPI_Device *device)
  2472. {
  2473. }
  2474. SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverNintendoClassic = {
  2475. SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC,
  2476. true,
  2477. HIDAPI_DriverNintendoClassic_RegisterHints,
  2478. HIDAPI_DriverNintendoClassic_UnregisterHints,
  2479. HIDAPI_DriverNintendoClassic_IsEnabled,
  2480. HIDAPI_DriverNintendoClassic_IsSupportedDevice,
  2481. HIDAPI_DriverSwitch_InitDevice,
  2482. HIDAPI_DriverSwitch_GetDevicePlayerIndex,
  2483. HIDAPI_DriverSwitch_SetDevicePlayerIndex,
  2484. HIDAPI_DriverSwitch_UpdateDevice,
  2485. HIDAPI_DriverSwitch_OpenJoystick,
  2486. HIDAPI_DriverSwitch_RumbleJoystick,
  2487. HIDAPI_DriverSwitch_RumbleJoystickTriggers,
  2488. HIDAPI_DriverSwitch_GetJoystickCapabilities,
  2489. HIDAPI_DriverSwitch_SetJoystickLED,
  2490. HIDAPI_DriverSwitch_SendJoystickEffect,
  2491. HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,
  2492. HIDAPI_DriverSwitch_CloseJoystick,
  2493. HIDAPI_DriverSwitch_FreeDevice,
  2494. };
  2495. SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverJoyCons = {
  2496. SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS,
  2497. true,
  2498. HIDAPI_DriverJoyCons_RegisterHints,
  2499. HIDAPI_DriverJoyCons_UnregisterHints,
  2500. HIDAPI_DriverJoyCons_IsEnabled,
  2501. HIDAPI_DriverJoyCons_IsSupportedDevice,
  2502. HIDAPI_DriverSwitch_InitDevice,
  2503. HIDAPI_DriverSwitch_GetDevicePlayerIndex,
  2504. HIDAPI_DriverSwitch_SetDevicePlayerIndex,
  2505. HIDAPI_DriverSwitch_UpdateDevice,
  2506. HIDAPI_DriverSwitch_OpenJoystick,
  2507. HIDAPI_DriverSwitch_RumbleJoystick,
  2508. HIDAPI_DriverSwitch_RumbleJoystickTriggers,
  2509. HIDAPI_DriverSwitch_GetJoystickCapabilities,
  2510. HIDAPI_DriverSwitch_SetJoystickLED,
  2511. HIDAPI_DriverSwitch_SendJoystickEffect,
  2512. HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,
  2513. HIDAPI_DriverSwitch_CloseJoystick,
  2514. HIDAPI_DriverSwitch_FreeDevice,
  2515. };
  2516. SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch = {
  2517. SDL_HINT_JOYSTICK_HIDAPI_SWITCH,
  2518. true,
  2519. HIDAPI_DriverSwitch_RegisterHints,
  2520. HIDAPI_DriverSwitch_UnregisterHints,
  2521. HIDAPI_DriverSwitch_IsEnabled,
  2522. HIDAPI_DriverSwitch_IsSupportedDevice,
  2523. HIDAPI_DriverSwitch_InitDevice,
  2524. HIDAPI_DriverSwitch_GetDevicePlayerIndex,
  2525. HIDAPI_DriverSwitch_SetDevicePlayerIndex,
  2526. HIDAPI_DriverSwitch_UpdateDevice,
  2527. HIDAPI_DriverSwitch_OpenJoystick,
  2528. HIDAPI_DriverSwitch_RumbleJoystick,
  2529. HIDAPI_DriverSwitch_RumbleJoystickTriggers,
  2530. HIDAPI_DriverSwitch_GetJoystickCapabilities,
  2531. HIDAPI_DriverSwitch_SetJoystickLED,
  2532. HIDAPI_DriverSwitch_SendJoystickEffect,
  2533. HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,
  2534. HIDAPI_DriverSwitch_CloseJoystick,
  2535. HIDAPI_DriverSwitch_FreeDevice,
  2536. };
  2537. #endif // SDL_JOYSTICK_HIDAPI_SWITCH
  2538. #endif // SDL_JOYSTICK_HIDAPI