1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 /* This driver supports the Nintendo Switch Pro controller.
22    Code and logic contributed by Valve Corporation under the SDL zlib license.
23 */
24 #include "../../SDL_internal.h"
25 
26 #ifdef SDL_JOYSTICK_HIDAPI
27 
28 #include "SDL_hints.h"
29 #include "SDL_events.h"
30 #include "SDL_timer.h"
31 #include "SDL_joystick.h"
32 #include "SDL_gamecontroller.h"
33 #include "../../SDL_hints_c.h"
34 #include "../SDL_sysjoystick.h"
35 #include "SDL_hidapijoystick_c.h"
36 #include "SDL_hidapi_rumble.h"
37 
38 
39 #ifdef SDL_JOYSTICK_HIDAPI_SWITCH
40 
41 /* Define this if you want to log all packets from the controller */
42 /*#define DEBUG_SWITCH_PROTOCOL*/
43 
44 /* Define this to get log output for rumble logic */
45 /*#define DEBUG_RUMBLE*/
46 
47 /* The initialization sequence doesn't appear to work correctly on Windows unless
48    the reads and writes are on the same thread.
49 
50    ... and now I can't reproduce this, so I'm leaving it in, but disabled for now.
51  */
52 /*#define SWITCH_SYNCHRONOUS_WRITES*/
53 
54 /* How often you can write rumble commands to the controller.
55    If you send commands more frequently than this, you can turn off the controller
56    in Bluetooth mode, or the motors can miss the command in USB mode.
57  */
58 #define RUMBLE_WRITE_FREQUENCY_MS   30
59 
60 /* How often you have to refresh a long duration rumble to keep the motors running */
61 #define RUMBLE_REFRESH_FREQUENCY_MS 50
62 
63 #define SWITCH_GYRO_SCALE      14.2842f
64 #define SWITCH_ACCEL_SCALE     4096.f
65 
66 typedef enum {
67     k_eSwitchInputReportIDs_SubcommandReply       = 0x21,
68     k_eSwitchInputReportIDs_FullControllerState   = 0x30,
69     k_eSwitchInputReportIDs_SimpleControllerState = 0x3F,
70     k_eSwitchInputReportIDs_CommandAck            = 0x81,
71 } ESwitchInputReportIDs;
72 
73 typedef enum {
74     k_eSwitchOutputReportIDs_RumbleAndSubcommand = 0x01,
75     k_eSwitchOutputReportIDs_Rumble              = 0x10,
76     k_eSwitchOutputReportIDs_Proprietary         = 0x80,
77 } ESwitchOutputReportIDs;
78 
79 typedef enum {
80     k_eSwitchSubcommandIDs_BluetoothManualPair = 0x01,
81     k_eSwitchSubcommandIDs_RequestDeviceInfo   = 0x02,
82     k_eSwitchSubcommandIDs_SetInputReportMode  = 0x03,
83     k_eSwitchSubcommandIDs_SetHCIState         = 0x06,
84     k_eSwitchSubcommandIDs_SPIFlashRead        = 0x10,
85     k_eSwitchSubcommandIDs_SetPlayerLights     = 0x30,
86     k_eSwitchSubcommandIDs_SetHomeLight        = 0x38,
87     k_eSwitchSubcommandIDs_EnableIMU           = 0x40,
88     k_eSwitchSubcommandIDs_SetIMUSensitivity   = 0x41,
89     k_eSwitchSubcommandIDs_EnableVibration     = 0x48,
90 } ESwitchSubcommandIDs;
91 
92 typedef enum {
93     k_eSwitchProprietaryCommandIDs_Status    = 0x01,
94     k_eSwitchProprietaryCommandIDs_Handshake = 0x02,
95     k_eSwitchProprietaryCommandIDs_HighSpeed = 0x03,
96     k_eSwitchProprietaryCommandIDs_ForceUSB  = 0x04,
97     k_eSwitchProprietaryCommandIDs_ClearUSB  = 0x05,
98     k_eSwitchProprietaryCommandIDs_ResetMCU  = 0x06,
99 } ESwitchProprietaryCommandIDs;
100 
101 typedef enum {
102     k_eSwitchDeviceInfoControllerType_Unknown        = 0x0,
103     k_eSwitchDeviceInfoControllerType_JoyConLeft     = 0x1,
104     k_eSwitchDeviceInfoControllerType_JoyConRight    = 0x2,
105     k_eSwitchDeviceInfoControllerType_ProController  = 0x3,
106 } ESwitchDeviceInfoControllerType;
107 
108 #define k_unSwitchOutputPacketDataLength 49
109 #define k_unSwitchMaxOutputPacketLength  64
110 #define k_unSwitchBluetoothPacketLength  k_unSwitchOutputPacketDataLength
111 #define k_unSwitchUSBPacketLength        k_unSwitchMaxOutputPacketLength
112 
113 #define k_unSPIStickCalibrationStartOffset  0x603D
114 #define k_unSPIStickCalibrationEndOffset    0x604E
115 #define k_unSPIStickCalibrationLength       (k_unSPIStickCalibrationEndOffset - k_unSPIStickCalibrationStartOffset + 1)
116 
117 #pragma pack(1)
118 typedef struct
119 {
120     Uint8 rgucButtons[2];
121     Uint8 ucStickHat;
122     Uint8 rgucJoystickLeft[2];
123     Uint8 rgucJoystickRight[2];
124 } SwitchInputOnlyControllerStatePacket_t;
125 
126 typedef struct
127 {
128     Uint8 rgucButtons[2];
129     Uint8 ucStickHat;
130     Sint16 sJoystickLeft[2];
131     Sint16 sJoystickRight[2];
132 } SwitchSimpleStatePacket_t;
133 
134 typedef struct
135 {
136     Uint8 ucCounter;
137     Uint8 ucBatteryAndConnection;
138     Uint8 rgucButtons[3];
139     Uint8 rgucJoystickLeft[3];
140     Uint8 rgucJoystickRight[3];
141     Uint8 ucVibrationCode;
142 } SwitchControllerStatePacket_t;
143 
144 typedef struct
145 {
146     SwitchControllerStatePacket_t controllerState;
147 
148     struct {
149         Sint16 sAccelX;
150         Sint16 sAccelY;
151         Sint16 sAccelZ;
152 
153         Sint16 sGyroX;
154         Sint16 sGyroY;
155         Sint16 sGyroZ;
156     } imuState[3];
157 } SwitchStatePacket_t;
158 
159 typedef struct
160 {
161     Uint32 unAddress;
162     Uint8 ucLength;
163 } SwitchSPIOpData_t;
164 
165 typedef struct
166 {
167     SwitchControllerStatePacket_t m_controllerState;
168 
169     Uint8 ucSubcommandAck;
170     Uint8 ucSubcommandID;
171 
172     #define k_unSubcommandDataBytes 35
173     union {
174         Uint8 rgucSubcommandData[k_unSubcommandDataBytes];
175 
176         struct {
177             SwitchSPIOpData_t opData;
178             Uint8 rgucReadData[k_unSubcommandDataBytes - sizeof(SwitchSPIOpData_t)];
179         } spiReadData;
180 
181         struct {
182             Uint8 rgucFirmwareVersion[2];
183             Uint8 ucDeviceType;
184             Uint8 ucFiller1;
185             Uint8 rgucMACAddress[6];
186             Uint8 ucFiller2;
187             Uint8 ucColorLocation;
188         } deviceInfo;
189     };
190 } SwitchSubcommandInputPacket_t;
191 
192 typedef struct
193 {
194 	Uint8 ucPacketType;
195 	Uint8 ucCommandID;
196 	Uint8 ucFiller;
197 
198 	Uint8 ucDeviceType;
199 	Uint8 rgucMACAddress[6];
200 } SwitchProprietaryStatusPacket_t;
201 
202 typedef struct
203 {
204     Uint8 rgucData[4];
205 } SwitchRumbleData_t;
206 
207 typedef struct
208 {
209     Uint8 ucPacketType;
210     Uint8 ucPacketNumber;
211     SwitchRumbleData_t rumbleData[2];
212 } SwitchCommonOutputPacket_t;
213 
214 typedef struct
215 {
216     SwitchCommonOutputPacket_t commonData;
217 
218     Uint8 ucSubcommandID;
219     Uint8 rgucSubcommandData[k_unSwitchOutputPacketDataLength - sizeof(SwitchCommonOutputPacket_t) - 1];
220 } SwitchSubcommandOutputPacket_t;
221 
222 typedef struct
223 {
224     Uint8 ucPacketType;
225     Uint8 ucProprietaryID;
226 
227     Uint8 rgucProprietaryData[k_unSwitchOutputPacketDataLength - 1 - 1];
228 } SwitchProprietaryOutputPacket_t;
229 #pragma pack()
230 
231 typedef struct {
232     SDL_HIDAPI_Device *device;
233     SDL_bool m_bInputOnly;
234     SDL_bool m_bHasHomeLED;
235     SDL_bool m_bUsingBluetooth;
236     SDL_bool m_bIsGameCube;
237     SDL_bool m_bUseButtonLabels;
238     ESwitchDeviceInfoControllerType m_eControllerType;
239     Uint8 m_rgucMACAddress[6];
240     Uint8 m_nCommandNumber;
241     SwitchCommonOutputPacket_t m_RumblePacket;
242     Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength];
243     SDL_bool m_bRumbleActive;
244     Uint32 m_unRumbleSent;
245     SDL_bool m_bRumblePending;
246     SDL_bool m_bRumbleZeroPending;
247     Uint32 m_unRumblePending;
248     SDL_bool m_bHasSensors;
249     SDL_bool m_bReportSensors;
250 
251     SwitchInputOnlyControllerStatePacket_t m_lastInputOnlyState;
252     SwitchSimpleStatePacket_t m_lastSimpleState;
253     SwitchStatePacket_t m_lastFullState;
254 
255     struct StickCalibrationData {
256         struct {
257             Sint16 sCenter;
258             Sint16 sMin;
259             Sint16 sMax;
260         } axis[2];
261     } m_StickCalData[2];
262 
263     struct StickExtents {
264         struct {
265             Sint16 sMin;
266             Sint16 sMax;
267         } axis[2];
268     } m_StickExtents[2];
269 } SDL_DriverSwitch_Context;
270 
271 
272 static SDL_bool
HasHomeLED(int vendor_id,int product_id)273 HasHomeLED(int vendor_id, int product_id)
274 {
275     /* The Power A Nintendo Switch Pro controllers don't have a Home LED */
276     if (vendor_id == 0 && product_id == 0) {
277         return SDL_FALSE;
278     }
279 
280     /* HORI Wireless Switch Pad */
281     if (vendor_id == 0x0f0d && product_id == 0x00f6) {
282         return SDL_FALSE;
283     }
284 
285     return SDL_TRUE;
286 }
287 
288 static SDL_bool
IsGameCubeFormFactor(int vendor_id,int product_id)289 IsGameCubeFormFactor(int vendor_id, int product_id)
290 {
291     static Uint32 gamecube_formfactor[] = {
292         MAKE_VIDPID(0x0e6f, 0x0185),    /* PDP Wired Fight Pad Pro for Nintendo Switch */
293         MAKE_VIDPID(0x20d6, 0xa711),    /* Core (Plus) Wired Controller */
294     };
295     Uint32 id = MAKE_VIDPID(vendor_id, product_id);
296     int i;
297 
298     for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) {
299         if (id == gamecube_formfactor[i]) {
300             return SDL_TRUE;
301         }
302     }
303     return SDL_FALSE;
304 }
305 
306 static SDL_bool
HIDAPI_DriverSwitch_IsSupportedDevice(const char * name,SDL_GameControllerType type,Uint16 vendor_id,Uint16 product_id,Uint16 version,int interface_number,int interface_class,int interface_subclass,int interface_protocol)307 HIDAPI_DriverSwitch_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
308 {
309     /* The HORI Wireless Switch Pad enumerates as a HID device when connected via USB
310        with the same VID/PID as when connected over Bluetooth but doesn't actually
311        support communication over USB. The most reliable way to block this without allowing the
312        controller to continually attempt to reconnect is to filter it out by manufactuer/product string.
313        Note that the controller does have a different product string when connected over Bluetooth.
314      */
315     if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) {
316         return SDL_FALSE;
317     }
318     return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE;
319 }
320 
321 static const char *
HIDAPI_DriverSwitch_GetDeviceName(Uint16 vendor_id,Uint16 product_id)322 HIDAPI_DriverSwitch_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
323 {
324     /* Give a user friendly name for this controller */
325     if (vendor_id == USB_VENDOR_NINTENDO) {
326         if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
327             return "Nintendo Switch Joy-Con Grip";
328         }
329 
330         if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_LEFT) {
331             return "Nintendo Switch Joy-Con Left";
332         }
333 
334         if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT) {
335             return "Nintendo Switch Joy-Con Right";
336         }
337     }
338 
339     return "Nintendo Switch Pro Controller";
340 }
341 
ReadInput(SDL_DriverSwitch_Context * ctx)342 static int ReadInput(SDL_DriverSwitch_Context *ctx)
343 {
344     /* Make sure we don't try to read at the same time a write is happening */
345     if (SDL_AtomicGet(&ctx->device->rumble_pending) > 0) {
346         return 0;
347     }
348 
349     return SDL_hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
350 }
351 
WriteOutput(SDL_DriverSwitch_Context * ctx,const Uint8 * data,int size)352 static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int size)
353 {
354 #ifdef SWITCH_SYNCHRONOUS_WRITES
355     return SDL_hid_write(ctx->device->dev, data, size);
356 #else
357     /* Use the rumble thread for general asynchronous writes */
358     if (SDL_HIDAPI_LockRumble() < 0) {
359         return -1;
360     }
361     return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size);
362 #endif /* SWITCH_SYNCHRONOUS_WRITES */
363 }
364 
ReadSubcommandReply(SDL_DriverSwitch_Context * ctx,ESwitchSubcommandIDs expectedID)365 static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID)
366 {
367     /* Average response time for messages is ~30ms */
368     Uint32 TimeoutMs = 100;
369     Uint32 startTicks = SDL_GetTicks();
370 
371     int nRead = 0;
372     while ((nRead = ReadInput(ctx)) != -1) {
373         if (nRead > 0) {
374             if (ctx->m_rgucReadBuffer[0] == k_eSwitchInputReportIDs_SubcommandReply) {
375                 SwitchSubcommandInputPacket_t *reply = (SwitchSubcommandInputPacket_t *)&ctx->m_rgucReadBuffer[1];
376                 if (reply->ucSubcommandID == expectedID && (reply->ucSubcommandAck & 0x80)) {
377                     return reply;
378                 }
379             }
380         } else {
381             SDL_Delay(1);
382         }
383 
384         if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) {
385             break;
386         }
387     }
388     return NULL;
389 }
390 
ReadProprietaryReply(SDL_DriverSwitch_Context * ctx,ESwitchProprietaryCommandIDs expectedID)391 static SDL_bool ReadProprietaryReply(SDL_DriverSwitch_Context *ctx, ESwitchProprietaryCommandIDs expectedID)
392 {
393     /* Average response time for messages is ~30ms */
394     Uint32 TimeoutMs = 100;
395     Uint32 startTicks = SDL_GetTicks();
396 
397     int nRead = 0;
398     while ((nRead = ReadInput(ctx)) != -1) {
399         if (nRead > 0) {
400             if (ctx->m_rgucReadBuffer[0] == k_eSwitchInputReportIDs_CommandAck && ctx->m_rgucReadBuffer[1] == expectedID) {
401                 return SDL_TRUE;
402             }
403         } else {
404             SDL_Delay(1);
405         }
406 
407         if (SDL_TICKS_PASSED(SDL_GetTicks(), startTicks + TimeoutMs)) {
408             break;
409         }
410     }
411     return SDL_FALSE;
412 }
413 
ConstructSubcommand(SDL_DriverSwitch_Context * ctx,ESwitchSubcommandIDs ucCommandID,Uint8 * pBuf,Uint8 ucLen,SwitchSubcommandOutputPacket_t * outPacket)414 static void ConstructSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs ucCommandID, Uint8 *pBuf, Uint8 ucLen, SwitchSubcommandOutputPacket_t *outPacket)
415 {
416     SDL_memset(outPacket, 0, sizeof(*outPacket));
417 
418     outPacket->commonData.ucPacketType = k_eSwitchOutputReportIDs_RumbleAndSubcommand;
419     outPacket->commonData.ucPacketNumber = ctx->m_nCommandNumber;
420 
421     SDL_memcpy(outPacket->commonData.rumbleData, ctx->m_RumblePacket.rumbleData, sizeof(ctx->m_RumblePacket.rumbleData));
422 
423     outPacket->ucSubcommandID = ucCommandID;
424     SDL_memcpy(outPacket->rgucSubcommandData, pBuf, ucLen);
425 
426     ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF;
427 }
428 
WritePacket(SDL_DriverSwitch_Context * ctx,void * pBuf,Uint8 ucLen)429 static SDL_bool WritePacket(SDL_DriverSwitch_Context *ctx, void *pBuf, Uint8 ucLen)
430 {
431     Uint8 rgucBuf[k_unSwitchMaxOutputPacketLength];
432     const size_t unWriteSize = ctx->m_bUsingBluetooth ? k_unSwitchBluetoothPacketLength : k_unSwitchUSBPacketLength;
433 
434     if (ucLen > k_unSwitchOutputPacketDataLength) {
435         return SDL_FALSE;
436     }
437 
438     if (ucLen < unWriteSize) {
439         SDL_memcpy(rgucBuf, pBuf, ucLen);
440         SDL_memset(rgucBuf+ucLen, 0, unWriteSize-ucLen);
441         pBuf = rgucBuf;
442         ucLen = (Uint8)unWriteSize;
443     }
444     return (WriteOutput(ctx, (Uint8 *)pBuf, ucLen) >= 0);
445 }
446 
WriteSubcommand(SDL_DriverSwitch_Context * ctx,ESwitchSubcommandIDs ucCommandID,Uint8 * pBuf,Uint8 ucLen,SwitchSubcommandInputPacket_t ** ppReply)447 static SDL_bool WriteSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs ucCommandID, Uint8 *pBuf, Uint8 ucLen, SwitchSubcommandInputPacket_t **ppReply)
448 {
449     int nRetries = 5;
450     SwitchSubcommandInputPacket_t *reply = NULL;
451 
452     while (!reply && nRetries--) {
453         SwitchSubcommandOutputPacket_t commandPacket;
454         ConstructSubcommand(ctx, ucCommandID, pBuf, ucLen, &commandPacket);
455 
456         if (!WritePacket(ctx, &commandPacket, sizeof(commandPacket))) {
457             continue;
458         }
459 
460         reply = ReadSubcommandReply(ctx, ucCommandID);
461     }
462 
463     if (ppReply) {
464         *ppReply = reply;
465     }
466     return reply != NULL;
467 }
468 
WriteProprietary(SDL_DriverSwitch_Context * ctx,ESwitchProprietaryCommandIDs ucCommand,Uint8 * pBuf,Uint8 ucLen,SDL_bool waitForReply)469 static SDL_bool WriteProprietary(SDL_DriverSwitch_Context *ctx, ESwitchProprietaryCommandIDs ucCommand, Uint8 *pBuf, Uint8 ucLen, SDL_bool waitForReply)
470 {
471     int nRetries = 5;
472 
473     while (nRetries--) {
474         SwitchProprietaryOutputPacket_t packet;
475 
476         if ((!pBuf && ucLen > 0) || ucLen > sizeof(packet.rgucProprietaryData)) {
477             return SDL_FALSE;
478         }
479 
480         SDL_zero(packet);
481         packet.ucPacketType = k_eSwitchOutputReportIDs_Proprietary;
482         packet.ucProprietaryID = ucCommand;
483         if (pBuf) {
484             SDL_memcpy(packet.rgucProprietaryData, pBuf, ucLen);
485         }
486 
487         if (!WritePacket(ctx, &packet, sizeof(packet))) {
488             continue;
489         }
490 
491         if (!waitForReply || ReadProprietaryReply(ctx, ucCommand)) {
492             return SDL_TRUE;
493         }
494     }
495     return SDL_FALSE;
496 }
497 
EncodeRumbleHighAmplitude(Uint16 amplitude)498 static Uint8 EncodeRumbleHighAmplitude(Uint16 amplitude) {
499     /* More information about these values can be found here:
500      * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
501      */
502     Uint16 hfa[101][2] = { {0, 0x0},{514, 0x2},{775, 0x4},{921, 0x6},{1096, 0x8},{1303, 0x0a},{1550, 0x0c},
503         {1843, 0x0e},{2192, 0x10},{2606, 0x12},{3100, 0x14},{3686, 0x16},{4383, 0x18},{5213, 0x1a},
504         {6199, 0x1c},{7372, 0x1e},{7698, 0x20},{8039, 0x22},{8395, 0x24},{8767, 0x26},{9155, 0x28},
505         {9560, 0x2a},{9984, 0x2c},{10426, 0x2e},{10887, 0x30},{11369, 0x32},{11873, 0x34},{12398, 0x36},
506         {12947, 0x38},{13520, 0x3a},{14119, 0x3c},{14744, 0x3e},{15067, 0x40},{15397, 0x42},{15734, 0x44},
507         {16079, 0x46},{16431, 0x48},{16790, 0x4a},{17158, 0x4c},{17534, 0x4e},{17918, 0x50},{18310, 0x52},
508         {18711, 0x54},{19121, 0x56},{19540, 0x58},{19967, 0x5a},{20405, 0x5c},{20851, 0x5e},{21308, 0x60},
509         {21775, 0x62},{22251, 0x64},{22739, 0x66},{23236, 0x68},{23745, 0x6a},{24265, 0x6c},{24797, 0x6e},
510         {25340, 0x70},{25894, 0x72},{26462, 0x74},{27041, 0x76},{27633, 0x78},{28238, 0x7a},{28856, 0x7c},
511         {29488, 0x7e},{30134, 0x80},{30794, 0x82},{31468, 0x84},{32157, 0x86},{32861, 0x88},{33581, 0x8a},
512         {34316, 0x8c},{35068, 0x8e},{35836, 0x90},{36620, 0x92},{37422, 0x94},{38242, 0x96},{39079, 0x98},
513         {39935, 0x9a},{40809, 0x9c},{41703, 0x9e},{42616, 0xa0},{43549, 0xa2},{44503, 0xa4},{45477, 0xa6},
514         {46473, 0xa8},{47491, 0xaa},{48531, 0xac},{49593, 0xae},{50679, 0xb0},{51789, 0xb2},{52923, 0xb4},
515         {54082, 0xb6},{55266, 0xb8},{56476, 0xba},{57713, 0xbc},{58977, 0xbe},{60268, 0xc0},{61588, 0xc2},
516         {62936, 0xc4},{64315, 0xc6},{65535, 0xc8} };
517     int index = 0;
518     for ( ; index < 101; index++) {
519         if (amplitude <= hfa[index][0]) {
520             return (Uint8)hfa[index][1];
521         }
522     }
523     return (Uint8)hfa[100][1];
524 }
525 
EncodeRumbleLowAmplitude(Uint16 amplitude)526 static Uint16 EncodeRumbleLowAmplitude(Uint16 amplitude) {
527     /* More information about these values can be found here:
528      * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
529      */
530     Uint16 lfa[101][2] = { {0, 0x0040},{514, 0x8040},{775, 0x0041},{921, 0x8041},{1096, 0x0042},
531         {1303, 0x8042},{1550, 0x0043},{1843, 0x8043},{2192, 0x0044},{2606, 0x8044},{3100, 0x0045},
532         {3686, 0x8045},{4383, 0x0046},{5213, 0x8046},{6199, 0x0047},{7372, 0x8047},{7698, 0x0048},
533         {8039, 0x8048},{8395, 0x0049},{8767, 0x8049},{9155, 0x004a},{9560, 0x804a},{9984, 0x004b},
534         {10426, 0x804b},{10887, 0x004c},{11369, 0x804c},{11873, 0x004d},{12398, 0x804d},{12947, 0x004e},
535         {13520, 0x804e},{14119, 0x004f},{14744, 0x804f},{15067, 0x0050},{15397, 0x8050},{15734, 0x0051},
536         {16079, 0x8051},{16431, 0x0052},{16790, 0x8052},{17158, 0x0053},{17534, 0x8053},{17918, 0x0054},
537         {18310, 0x8054},{18711, 0x0055},{19121, 0x8055},{19540, 0x0056},{19967, 0x8056},{20405, 0x0057},
538         {20851, 0x8057},{21308, 0x0058},{21775, 0x8058},{22251, 0x0059},{22739, 0x8059},{23236, 0x005a},
539         {23745, 0x805a},{24265, 0x005b},{24797, 0x805b},{25340, 0x005c},{25894, 0x805c},{26462, 0x005d},
540         {27041, 0x805d},{27633, 0x005e},{28238, 0x805e},{28856, 0x005f},{29488, 0x805f},{30134, 0x0060},
541         {30794, 0x8060},{31468, 0x0061},{32157, 0x8061},{32861, 0x0062},{33581, 0x8062},{34316, 0x0063},
542         {35068, 0x8063},{35836, 0x0064},{36620, 0x8064},{37422, 0x0065},{38242, 0x8065},{39079, 0x0066},
543         {39935, 0x8066},{40809, 0x0067},{41703, 0x8067},{42616, 0x0068},{43549, 0x8068},{44503, 0x0069},
544         {45477, 0x8069},{46473, 0x006a},{47491, 0x806a},{48531, 0x006b},{49593, 0x806b},{50679, 0x006c},
545         {51789, 0x806c},{52923, 0x006d},{54082, 0x806d},{55266, 0x006e},{56476, 0x806e},{57713, 0x006f},
546         {58977, 0x806f},{60268, 0x0070},{61588, 0x8070},{62936, 0x0071},{64315, 0x8071},{65535, 0x0072} };
547     int index = 0;
548     for (; index < 101; index++) {
549         if (amplitude <= lfa[index][0]) {
550             return lfa[index][1];
551         }
552     }
553     return lfa[100][1];
554 }
555 
SetNeutralRumble(SwitchRumbleData_t * pRumble)556 static void SetNeutralRumble(SwitchRumbleData_t *pRumble)
557 {
558     pRumble->rgucData[0] = 0x00;
559     pRumble->rgucData[1] = 0x01;
560     pRumble->rgucData[2] = 0x40;
561     pRumble->rgucData[3] = 0x40;
562 }
563 
EncodeRumble(SwitchRumbleData_t * pRumble,Uint16 usHighFreq,Uint8 ucHighFreqAmp,Uint8 ucLowFreq,Uint16 usLowFreqAmp)564 static void EncodeRumble(SwitchRumbleData_t *pRumble, Uint16 usHighFreq, Uint8 ucHighFreqAmp, Uint8 ucLowFreq, Uint16 usLowFreqAmp)
565 {
566     if (ucHighFreqAmp > 0 || usLowFreqAmp > 0) {
567         // High-band frequency and low-band amplitude are actually nine-bits each so they
568         // take a bit from the high-band amplitude and low-band frequency bytes respectively
569         pRumble->rgucData[0] = usHighFreq & 0xFF;
570         pRumble->rgucData[1] = ucHighFreqAmp | ((usHighFreq >> 8) & 0x01);
571 
572         pRumble->rgucData[2]  = ucLowFreq | ((usLowFreqAmp >> 8) & 0x80);
573         pRumble->rgucData[3]  = usLowFreqAmp & 0xFF;
574 
575 #ifdef DEBUG_RUMBLE
576         SDL_Log("Freq: %.2X %.2X  %.2X, Amp: %.2X  %.2X %.2X\n",
577             usHighFreq & 0xFF, ((usHighFreq >> 8) & 0x01), ucLowFreq,
578             ucHighFreqAmp, ((usLowFreqAmp >> 8) & 0x80), usLowFreqAmp & 0xFF);
579 #endif
580     } else {
581         SetNeutralRumble(pRumble);
582     }
583 }
584 
WriteRumble(SDL_DriverSwitch_Context * ctx)585 static SDL_bool WriteRumble(SDL_DriverSwitch_Context *ctx)
586 {
587     /* Write into m_RumblePacket rather than a temporary buffer to allow the current rumble state
588      * to be retained for subsequent rumble or subcommand packets sent to the controller
589      */
590     ctx->m_RumblePacket.ucPacketType = k_eSwitchOutputReportIDs_Rumble;
591     ctx->m_RumblePacket.ucPacketNumber = ctx->m_nCommandNumber;
592     ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF;
593 
594     /* Refresh the rumble state periodically */
595     ctx->m_unRumbleSent = SDL_GetTicks();
596 
597     return WritePacket(ctx, (Uint8 *)&ctx->m_RumblePacket, sizeof(ctx->m_RumblePacket));
598 }
599 
BReadDeviceInfo(SDL_DriverSwitch_Context * ctx)600 static SDL_bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx)
601 {
602     SwitchSubcommandInputPacket_t *reply = NULL;
603 
604     ctx->m_bUsingBluetooth = SDL_FALSE;
605 
606     if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, SDL_TRUE)) {
607         SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0];
608         size_t i;
609 
610         ctx->m_eControllerType = (ESwitchDeviceInfoControllerType)status->ucDeviceType;
611         for (i = 0; i < sizeof (ctx->m_rgucMACAddress); ++i)
612             ctx->m_rgucMACAddress[i] = status->rgucMACAddress[ sizeof(ctx->m_rgucMACAddress) - i - 1 ];
613 
614         return SDL_TRUE;
615     }
616 
617     ctx->m_bUsingBluetooth = SDL_TRUE;
618 
619     if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) {
620         // Byte 2: Controller ID (1=LJC, 2=RJC, 3=Pro)
621         ctx->m_eControllerType = (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType;
622 
623         // Bytes 4-9: MAC address (big-endian)
624         SDL_memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
625 
626         return SDL_TRUE;
627     }
628 
629     ctx->m_bUsingBluetooth = SDL_FALSE;
630 
631     return SDL_FALSE;
632 }
633 
BTrySetupUSB(SDL_DriverSwitch_Context * ctx)634 static SDL_bool BTrySetupUSB(SDL_DriverSwitch_Context *ctx)
635 {
636     /* We have to send a connection handshake to the controller when communicating over USB
637      * before we're able to send it other commands. Luckily this command is not supported
638      * over Bluetooth, so we can use the controller's lack of response as a way to
639      * determine if the connection is over USB or Bluetooth
640      */
641     if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Handshake, NULL, 0, SDL_TRUE)) {
642         return SDL_FALSE;
643     }
644     if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_HighSpeed, NULL, 0, SDL_TRUE)) {
645         /* The 8BitDo M30 and SF30 Pro don't respond to this command, but otherwise work correctly */
646         /*return SDL_FALSE;*/
647     }
648     if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Handshake, NULL, 0, SDL_TRUE)) {
649         /* This fails on the right Joy-Con when plugged into the charging grip */
650         /*return SDL_FALSE;*/
651     }
652     if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE)) {
653         return SDL_FALSE;
654     }
655     return SDL_TRUE;
656 }
657 
SetVibrationEnabled(SDL_DriverSwitch_Context * ctx,Uint8 enabled)658 static SDL_bool SetVibrationEnabled(SDL_DriverSwitch_Context *ctx, Uint8 enabled)
659 {
660     return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_EnableVibration, &enabled, sizeof(enabled), NULL);
661 
662 }
SetInputMode(SDL_DriverSwitch_Context * ctx,Uint8 input_mode)663 static SDL_bool SetInputMode(SDL_DriverSwitch_Context *ctx, Uint8 input_mode)
664 {
665     return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetInputReportMode, &input_mode, 1, NULL);
666 }
667 
SetHomeLED(SDL_DriverSwitch_Context * ctx,Uint8 brightness)668 static SDL_bool SetHomeLED(SDL_DriverSwitch_Context *ctx, Uint8 brightness)
669 {
670     Uint8 ucLedIntensity = 0;
671     Uint8 rgucBuffer[4];
672 
673     if (brightness > 0) {
674         if (brightness < 65) {
675             ucLedIntensity = (brightness + 5) / 10;
676         } else {
677             ucLedIntensity = (Uint8)SDL_ceilf(0xF * SDL_powf((float)brightness / 100.f, 2.13f));
678         }
679     }
680 
681     rgucBuffer[0] = (0x0 << 4) | 0x1;  /* 0 mini cycles (besides first), cycle duration 8ms */
682     rgucBuffer[1] = ((ucLedIntensity & 0xF) << 4) | 0x0;  /* LED start intensity (0x0-0xF), 0 cycles (LED stays on at start intensity after first cycle) */
683     rgucBuffer[2] = ((ucLedIntensity & 0xF) << 4) | 0x0;  /* First cycle LED intensity, 0x0 intensity for second cycle */
684     rgucBuffer[3] = (0x0 << 4) | 0x0;  /* 8ms fade transition to first cycle, 8ms first cycle LED duration */
685 
686     return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetHomeLight, rgucBuffer, sizeof(rgucBuffer), NULL);
687 }
688 
SetSlotLED(SDL_DriverSwitch_Context * ctx,Uint8 slot)689 static SDL_bool SetSlotLED(SDL_DriverSwitch_Context *ctx, Uint8 slot)
690 {
691     Uint8 led_data = (1 << slot);
692     return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetPlayerLights, &led_data, sizeof(led_data), NULL);
693 }
694 
SetIMUEnabled(SDL_DriverSwitch_Context * ctx,SDL_bool enabled)695 static SDL_bool SetIMUEnabled(SDL_DriverSwitch_Context* ctx, SDL_bool enabled)
696 {
697     Uint8 imu_data = enabled ? 1 : 0;
698     return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_EnableIMU, &imu_data, sizeof(imu_data), NULL);
699 }
700 
LoadStickCalibration(SDL_DriverSwitch_Context * ctx,Uint8 input_mode)701 static SDL_bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx, Uint8 input_mode)
702 {
703     Uint8 *pStickCal;
704     size_t stick, axis;
705     SwitchSubcommandInputPacket_t *reply = NULL;
706 
707     /* Read Calibration Info */
708     SwitchSPIOpData_t readParams;
709     readParams.unAddress = k_unSPIStickCalibrationStartOffset;
710     readParams.ucLength = k_unSPIStickCalibrationLength;
711 
712     if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readParams, sizeof(readParams), &reply)) {
713         return SDL_FALSE;
714     }
715 
716     /* Stick calibration values are 12-bits each and are packed by bit
717      * For whatever reason the fields are in a different order for each stick
718      * Left:  X-Max, Y-Max, X-Center, Y-Center, X-Min, Y-Min
719      * Right: X-Center, Y-Center, X-Min, Y-Min, X-Max, Y-Max
720      */
721     pStickCal = reply->spiReadData.rgucReadData;
722 
723     /* Left stick */
724     ctx->m_StickCalData[0].axis[0].sMax    = ((pStickCal[1] << 8) & 0xF00) | pStickCal[0];     /* X Axis max above center */
725     ctx->m_StickCalData[0].axis[1].sMax    = (pStickCal[2] << 4) | (pStickCal[1] >> 4);         /* Y Axis max above center */
726     ctx->m_StickCalData[0].axis[0].sCenter = ((pStickCal[4] << 8) & 0xF00) | pStickCal[3];     /* X Axis center */
727     ctx->m_StickCalData[0].axis[1].sCenter = (pStickCal[5] << 4) | (pStickCal[4] >> 4);        /* Y Axis center */
728     ctx->m_StickCalData[0].axis[0].sMin    = ((pStickCal[7] << 8) & 0xF00) | pStickCal[6];      /* X Axis min below center */
729     ctx->m_StickCalData[0].axis[1].sMin    = (pStickCal[8] << 4) | (pStickCal[7] >> 4);        /* Y Axis min below center */
730 
731     /* Right stick */
732     ctx->m_StickCalData[1].axis[0].sCenter = ((pStickCal[10] << 8) & 0xF00) | pStickCal[9];     /* X Axis center */
733     ctx->m_StickCalData[1].axis[1].sCenter = (pStickCal[11] << 4) | (pStickCal[10] >> 4);      /* Y Axis center */
734     ctx->m_StickCalData[1].axis[0].sMin    = ((pStickCal[13] << 8) & 0xF00) | pStickCal[12];    /* X Axis min below center */
735     ctx->m_StickCalData[1].axis[1].sMin    = (pStickCal[14] << 4) | (pStickCal[13] >> 4);      /* Y Axis min below center */
736     ctx->m_StickCalData[1].axis[0].sMax    = ((pStickCal[16] << 8) & 0xF00) | pStickCal[15];    /* X Axis max above center */
737     ctx->m_StickCalData[1].axis[1].sMax    = (pStickCal[17] << 4) | (pStickCal[16] >> 4);      /* Y Axis max above center */
738 
739     /* Filter out any values that were uninitialized (0xFFF) in the SPI read */
740     for (stick = 0; stick < 2; ++stick) {
741         for (axis = 0; axis < 2; ++axis) {
742             if (ctx->m_StickCalData[stick].axis[axis].sCenter == 0xFFF) {
743                 ctx->m_StickCalData[stick].axis[axis].sCenter = 0;
744             }
745             if (ctx->m_StickCalData[stick].axis[axis].sMax == 0xFFF) {
746                 ctx->m_StickCalData[stick].axis[axis].sMax = 0;
747             }
748             if (ctx->m_StickCalData[stick].axis[axis].sMin == 0xFFF) {
749                 ctx->m_StickCalData[stick].axis[axis].sMin = 0;
750             }
751         }
752     }
753 
754     if (input_mode == k_eSwitchInputReportIDs_SimpleControllerState) {
755         for (stick = 0; stick < 2; ++stick) {
756             for(axis = 0; axis < 2; ++axis) {
757                 ctx->m_StickExtents[stick].axis[axis].sMin = (Sint16)(SDL_MIN_SINT16 * 0.5f);
758                 ctx->m_StickExtents[stick].axis[axis].sMax = (Sint16)(SDL_MAX_SINT16 * 0.5f);
759             }
760         }
761     } else {
762         for (stick = 0; stick < 2; ++stick) {
763             for(axis = 0; axis < 2; ++axis) {
764                 ctx->m_StickExtents[stick].axis[axis].sMin = -(Sint16)(ctx->m_StickCalData[stick].axis[axis].sMin * 0.7f);
765                 ctx->m_StickExtents[stick].axis[axis].sMax = (Sint16)(ctx->m_StickCalData[stick].axis[axis].sMax * 0.7f);
766             }
767         }
768     }
769     return SDL_TRUE;
770 }
771 
ApplyStickCalibrationCentered(SDL_DriverSwitch_Context * ctx,int nStick,int nAxis,Sint16 sRawValue,Sint16 sCenter)772 static Sint16 ApplyStickCalibrationCentered(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue, Sint16 sCenter)
773 {
774     sRawValue -= sCenter;
775 
776     if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
777         ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
778     }
779     if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
780         ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
781     }
782 
783     return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
784 }
785 
ApplyStickCalibration(SDL_DriverSwitch_Context * ctx,int nStick,int nAxis,Sint16 sRawValue)786 static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
787 {
788     return ApplyStickCalibrationCentered(ctx, nStick, nAxis, sRawValue, ctx->m_StickCalData[nStick].axis[nAxis].sCenter);
789 }
790 
SDL_GameControllerButtonReportingHintChanged(void * userdata,const char * name,const char * oldValue,const char * hint)791 static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
792 {
793     SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata;
794     ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
795 }
796 
RemapButton(SDL_DriverSwitch_Context * ctx,Uint8 button)797 static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
798 {
799     if (!ctx->m_bUseButtonLabels) {
800         /* Use button positions */
801         if (ctx->m_bIsGameCube) {
802             switch (button) {
803             case SDL_CONTROLLER_BUTTON_B:
804                 return SDL_CONTROLLER_BUTTON_X;
805             case SDL_CONTROLLER_BUTTON_X:
806                 return SDL_CONTROLLER_BUTTON_B;
807             default:
808                 break;
809             }
810         } else {
811             switch (button) {
812             case SDL_CONTROLLER_BUTTON_A:
813                 return SDL_CONTROLLER_BUTTON_B;
814             case SDL_CONTROLLER_BUTTON_B:
815                 return SDL_CONTROLLER_BUTTON_A;
816             case SDL_CONTROLLER_BUTTON_X:
817                 return SDL_CONTROLLER_BUTTON_Y;
818             case SDL_CONTROLLER_BUTTON_Y:
819                 return SDL_CONTROLLER_BUTTON_X;
820             default:
821                 break;
822             }
823         }
824     }
825     return button;
826 }
827 
828 static SDL_bool
HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device * device)829 HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
830 {
831     return HIDAPI_JoystickConnected(device, NULL);
832 }
833 
834 static int
HIDAPI_DriverSwitch_GetDevicePlayerIndex(SDL_HIDAPI_Device * device,SDL_JoystickID instance_id)835 HIDAPI_DriverSwitch_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
836 {
837     return -1;
838 }
839 
840 static void
HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device * device,SDL_JoystickID instance_id,int player_index)841 HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
842 {
843 }
844 
845 static SDL_bool
HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)846 HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
847 {
848     SDL_DriverSwitch_Context *ctx;
849     Uint8 input_mode;
850 
851     ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx));
852     if (!ctx) {
853         SDL_OutOfMemory();
854         goto error;
855     }
856     ctx->device = device;
857     device->context = ctx;
858 
859     device->dev = SDL_hid_open_path(device->path, 0);
860     if (!device->dev) {
861         SDL_SetError("Couldn't open %s", device->path);
862         goto error;
863     }
864 
865     /* Find out whether or not we can send output reports */
866     ctx->m_bInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(device->vendor_id, device->product_id);
867     if (!ctx->m_bInputOnly) {
868         ctx->m_bHasHomeLED = HasHomeLED(device->vendor_id, device->product_id);
869 
870         /* Initialize rumble data */
871         SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
872         SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
873 
874         if (!BReadDeviceInfo(ctx)) {
875             SDL_SetError("Couldn't read device info");
876             goto error;
877         }
878 
879         if (!ctx->m_bUsingBluetooth) {
880             if (!BTrySetupUSB(ctx)) {
881                 SDL_SetError("Couldn't setup USB mode");
882                 goto error;
883             }
884         }
885 
886         /* Determine the desired input mode (needed before loading stick calibration) */
887         if (ctx->m_bUsingBluetooth) {
888             input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
889         } else {
890             input_mode = k_eSwitchInputReportIDs_FullControllerState;
891         }
892 
893         /* The official Nintendo Switch Pro Controller supports FullControllerState over bluetooth
894          * just fine. We really should use that, or else the epowerlevel code in
895          * HandleFullControllerState is completely pointless. We need full state if we want battery
896          * level and we only care about battery level over bluetooth anyway.
897          */
898         if (device->vendor_id == USB_VENDOR_NINTENDO &&
899                 (device->product_id == USB_PRODUCT_NINTENDO_SWITCH_PRO ||
900                 device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP ||
901                 device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_LEFT ||
902                 device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT)) {
903             input_mode = k_eSwitchInputReportIDs_FullControllerState;
904         }
905 
906         if (input_mode == k_eSwitchInputReportIDs_FullControllerState) {
907             SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 200.0f);
908             SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 200.0f);
909             ctx->m_bHasSensors = SDL_TRUE;
910         }
911 
912         if (!LoadStickCalibration(ctx, input_mode)) {
913             SDL_SetError("Couldn't load stick calibration");
914             goto error;
915         }
916 
917         if (!SetVibrationEnabled(ctx, 1)) {
918             SDL_SetError("Couldn't enable vibration");
919             goto error;
920         }
921 
922         /* Set desired input mode */
923         if (!SetInputMode(ctx, input_mode)) {
924             SDL_SetError("Couldn't set input mode");
925             goto error;
926         }
927 
928         /* Start sending USB reports */
929         if (!ctx->m_bUsingBluetooth) {
930             /* ForceUSB doesn't generate an ACK, so don't wait for a reply */
931             if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE)) {
932                 SDL_SetError("Couldn't start USB reports");
933                 goto error;
934             }
935         }
936 
937         /* Set the LED state */
938         if (ctx->m_bHasHomeLED) {
939             const char *hint = SDL_GetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED);
940             if (hint && *hint) {
941                 if (SDL_GetStringBoolean(hint, SDL_TRUE)) {
942                     SetHomeLED(ctx, 100);
943                 } else {
944                     SetHomeLED(ctx, 0);
945                 }
946             }
947         }
948         SetSlotLED(ctx, (joystick->instance_id % 4));
949 
950         /* Set the serial number */
951         {
952             char serial[18];
953 
954             SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
955                 ctx->m_rgucMACAddress[0],
956                 ctx->m_rgucMACAddress[1],
957                 ctx->m_rgucMACAddress[2],
958                 ctx->m_rgucMACAddress[3],
959                 ctx->m_rgucMACAddress[4],
960                 ctx->m_rgucMACAddress[5]);
961             joystick->serial = SDL_strdup(serial);
962         }
963     }
964 
965     if (IsGameCubeFormFactor(device->vendor_id, device->product_id)) {
966         /* This is a controller shaped like a GameCube controller, with a large central A button */
967         ctx->m_bIsGameCube = SDL_TRUE;
968     }
969 
970     SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
971                         SDL_GameControllerButtonReportingHintChanged, ctx);
972 
973     /* Initialize the joystick capabilities */
974     if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
975         ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
976         joystick->nbuttons = 20;
977     } else {
978         joystick->nbuttons = 16;
979     }
980     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
981     joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
982 
983     return SDL_TRUE;
984 
985 error:
986     SDL_LockMutex(device->dev_lock);
987     {
988         if (device->dev) {
989             SDL_hid_close(device->dev);
990             device->dev = NULL;
991         }
992         if (device->context) {
993             SDL_free(device->context);
994             device->context = NULL;
995         }
996     }
997     SDL_UnlockMutex(device->dev_lock);
998     return SDL_FALSE;
999 }
1000 
1001 static int
HIDAPI_DriverSwitch_ActuallyRumbleJoystick(SDL_DriverSwitch_Context * ctx,Uint16 low_frequency_rumble,Uint16 high_frequency_rumble)1002 HIDAPI_DriverSwitch_ActuallyRumbleJoystick(SDL_DriverSwitch_Context *ctx, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1003 {
1004     /* Experimentally determined rumble values. These will only matter on some controllers as tested ones
1005      * seem to disregard these and just use any non-zero rumble values as a binary flag for constant rumble
1006      *
1007      * More information about these values can be found here:
1008      * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
1009      */
1010     const Uint16 k_usHighFreq = 0x0074;
1011     const Uint8  k_ucHighFreqAmp = EncodeRumbleHighAmplitude(high_frequency_rumble);
1012     const Uint8  k_ucLowFreq = 0x3D;
1013     const Uint16 k_usLowFreqAmp = EncodeRumbleLowAmplitude(low_frequency_rumble);
1014 
1015     if (low_frequency_rumble || high_frequency_rumble) {
1016         EncodeRumble(&ctx->m_RumblePacket.rumbleData[0], k_usHighFreq, k_ucHighFreqAmp, k_ucLowFreq, k_usLowFreqAmp);
1017         EncodeRumble(&ctx->m_RumblePacket.rumbleData[1], k_usHighFreq, k_ucHighFreqAmp, k_ucLowFreq, k_usLowFreqAmp);
1018     } else {
1019         SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
1020         SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
1021     }
1022 
1023     ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE;
1024 
1025     if (!WriteRumble(ctx)) {
1026         SDL_SetError("Couldn't send rumble packet");
1027         return -1;
1028     }
1029     return 0;
1030 }
1031 
1032 static int
HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context * ctx)1033 HIDAPI_DriverSwitch_SendPendingRumble(SDL_DriverSwitch_Context *ctx)
1034 {
1035     if (!SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_unRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) {
1036         return 0;
1037     }
1038 
1039     if (ctx->m_bRumblePending) {
1040         Uint16 low_frequency_rumble = (Uint16)(ctx->m_unRumblePending >> 16);
1041         Uint16 high_frequency_rumble = (Uint16)ctx->m_unRumblePending;
1042 
1043 #ifdef DEBUG_RUMBLE
1044         SDL_Log("Sent pending rumble %d/%d, %d ms after previous rumble\n", low_frequency_rumble, high_frequency_rumble, SDL_GetTicks() - ctx->m_unRumbleSent);
1045 #endif
1046         ctx->m_bRumblePending = SDL_FALSE;
1047         ctx->m_unRumblePending = 0;
1048 
1049         return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, low_frequency_rumble, high_frequency_rumble);
1050     }
1051 
1052     if (ctx->m_bRumbleZeroPending) {
1053         ctx->m_bRumbleZeroPending = SDL_FALSE;
1054 
1055 #ifdef DEBUG_RUMBLE
1056         SDL_Log("Sent pending zero rumble, %d ms after previous rumble\n", SDL_GetTicks() - ctx->m_unRumbleSent);
1057 #endif
1058         return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, 0, 0);
1059     }
1060 
1061     return 0;
1062 }
1063 
1064 static int
HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,Uint16 low_frequency_rumble,Uint16 high_frequency_rumble)1065 HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1066 {
1067     SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
1068 
1069     if (ctx->m_bInputOnly) {
1070         return SDL_Unsupported();
1071     }
1072 
1073     if (ctx->m_bRumblePending) {
1074         if (HIDAPI_DriverSwitch_SendPendingRumble(ctx) < 0) {
1075             return -1;
1076         }
1077     }
1078 
1079     if (!SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_unRumbleSent + RUMBLE_WRITE_FREQUENCY_MS)) {
1080         if (low_frequency_rumble || high_frequency_rumble) {
1081             Uint32 unRumblePending = ((Uint32)low_frequency_rumble << 16) | high_frequency_rumble;
1082 
1083             /* Keep the highest rumble intensity in the given interval */
1084             if (unRumblePending > ctx->m_unRumblePending) {
1085                 ctx->m_unRumblePending = unRumblePending;
1086             }
1087             ctx->m_bRumblePending = SDL_TRUE;
1088             ctx->m_bRumbleZeroPending = SDL_FALSE;
1089         } else {
1090             /* When rumble is complete, turn it off */
1091             ctx->m_bRumbleZeroPending = SDL_TRUE;
1092         }
1093         return 0;
1094     }
1095 
1096 #ifdef DEBUG_RUMBLE
1097     SDL_Log("Sent rumble %d/%d\n", low_frequency_rumble, high_frequency_rumble);
1098 #endif
1099 
1100     return HIDAPI_DriverSwitch_ActuallyRumbleJoystick(ctx, low_frequency_rumble, high_frequency_rumble);
1101 }
1102 
1103 static int
HIDAPI_DriverSwitch_RumbleJoystickTriggers(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,Uint16 left_rumble,Uint16 right_rumble)1104 HIDAPI_DriverSwitch_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
1105 {
1106     return SDL_Unsupported();
1107 }
1108 
1109 static Uint32
HIDAPI_DriverSwitch_GetJoystickCapabilities(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)1110 HIDAPI_DriverSwitch_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1111 {
1112     SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
1113     Uint32 result = 0;
1114 
1115     if (!ctx->m_bInputOnly) {
1116         /* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */
1117         result |= SDL_JOYCAP_RUMBLE;
1118     }
1119 
1120     return result;
1121 }
1122 
1123 static int
HIDAPI_DriverSwitch_SetJoystickLED(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,Uint8 red,Uint8 green,Uint8 blue)1124 HIDAPI_DriverSwitch_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
1125 {
1126     return SDL_Unsupported();
1127 }
1128 
1129 static int
HIDAPI_DriverSwitch_SendJoystickEffect(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,const void * data,int size)1130 HIDAPI_DriverSwitch_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
1131 {
1132     return SDL_Unsupported();
1133 }
1134 
1135 static int
HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,SDL_bool enabled)1136 HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
1137 {
1138     SDL_DriverSwitch_Context* ctx = (SDL_DriverSwitch_Context*)device->context;
1139 
1140     if (!ctx->m_bHasSensors) {
1141         return SDL_Unsupported();
1142     }
1143 
1144     SetIMUEnabled(ctx, enabled);
1145     ctx->m_bReportSensors = enabled;
1146 
1147     return 0;
1148 }
1149 
1150 static float
HIDAPI_DriverSwitch_ScaleGyro(Sint16 value)1151 HIDAPI_DriverSwitch_ScaleGyro(Sint16 value)
1152 {
1153     float result = (value / SWITCH_GYRO_SCALE) * (float)M_PI / 180.0f;
1154     return result;
1155 }
1156 
1157 static float
HIDAPI_DriverSwitch_ScaleAccel(Sint16 value)1158 HIDAPI_DriverSwitch_ScaleAccel(Sint16 value)
1159 {
1160     float result = (value / SWITCH_ACCEL_SCALE) * SDL_STANDARD_GRAVITY;
1161     return result;
1162 }
1163 
HandleInputOnlyControllerState(SDL_Joystick * joystick,SDL_DriverSwitch_Context * ctx,SwitchInputOnlyControllerStatePacket_t * packet)1164 static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet)
1165 {
1166     Sint16 axis;
1167 
1168     if (packet->rgucButtons[0] != ctx->m_lastInputOnlyState.rgucButtons[0]) {
1169         Uint8 data = packet->rgucButtons[0];
1170         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
1171         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
1172         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
1173         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
1174         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
1175         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
1176 
1177         axis = (data & 0x40) ? 32767 : -32768;
1178         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
1179 
1180         axis = (data & 0x80) ? 32767 : -32768;
1181         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
1182     }
1183 
1184     if (packet->rgucButtons[1] != ctx->m_lastInputOnlyState.rgucButtons[1]) {
1185         Uint8 data = packet->rgucButtons[1];
1186         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
1187         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
1188         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
1189         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
1190         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
1191         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
1192     }
1193 
1194     if (packet->ucStickHat != ctx->m_lastInputOnlyState.ucStickHat) {
1195         SDL_bool dpad_up = SDL_FALSE;
1196         SDL_bool dpad_down = SDL_FALSE;
1197         SDL_bool dpad_left = SDL_FALSE;
1198         SDL_bool dpad_right = SDL_FALSE;
1199 
1200         switch (packet->ucStickHat) {
1201         case 0:
1202             dpad_up = SDL_TRUE;
1203             break;
1204         case 1:
1205             dpad_up = SDL_TRUE;
1206             dpad_right = SDL_TRUE;
1207             break;
1208         case 2:
1209             dpad_right = SDL_TRUE;
1210             break;
1211         case 3:
1212             dpad_right = SDL_TRUE;
1213             dpad_down = SDL_TRUE;
1214             break;
1215         case 4:
1216             dpad_down = SDL_TRUE;
1217             break;
1218         case 5:
1219             dpad_left = SDL_TRUE;
1220             dpad_down = SDL_TRUE;
1221             break;
1222         case 6:
1223             dpad_left = SDL_TRUE;
1224             break;
1225         case 7:
1226             dpad_up = SDL_TRUE;
1227             dpad_left = SDL_TRUE;
1228             break;
1229         default:
1230             break;
1231         }
1232         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
1233         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
1234         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
1235         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
1236     }
1237 
1238     if (packet->rgucJoystickLeft[0] != ctx->m_lastInputOnlyState.rgucJoystickLeft[0]) {
1239         axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickLeft[0], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
1240         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
1241     }
1242 
1243     if (packet->rgucJoystickLeft[1] != ctx->m_lastInputOnlyState.rgucJoystickLeft[1]) {
1244         axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickLeft[1], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
1245         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
1246     }
1247 
1248     if (packet->rgucJoystickRight[0] != ctx->m_lastInputOnlyState.rgucJoystickRight[0]) {
1249         axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickRight[0], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
1250         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
1251     }
1252 
1253     if (packet->rgucJoystickRight[1] != ctx->m_lastInputOnlyState.rgucJoystickRight[1]) {
1254         axis = (Sint16)HIDAPI_RemapVal(packet->rgucJoystickRight[1], SDL_MIN_UINT8, SDL_MAX_UINT8, SDL_MIN_SINT16, SDL_MAX_SINT16);
1255         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
1256     }
1257 
1258     ctx->m_lastInputOnlyState = *packet;
1259 }
1260 
HandleSimpleControllerState(SDL_Joystick * joystick,SDL_DriverSwitch_Context * ctx,SwitchSimpleStatePacket_t * packet)1261 static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchSimpleStatePacket_t *packet)
1262 {
1263     /* 0x8000 is the neutral value for all joystick axes */
1264     const Uint16 usJoystickCenter = 0x8000;
1265     Sint16 axis;
1266 
1267     if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
1268         Uint8 data = packet->rgucButtons[0];
1269         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
1270         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
1271         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
1272         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
1273         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
1274         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
1275 
1276         axis = (data & 0x40) ? 32767 : -32768;
1277         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
1278 
1279         axis = (data & 0x80) ? 32767 : -32768;
1280         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
1281     }
1282 
1283     if (packet->rgucButtons[1] != ctx->m_lastSimpleState.rgucButtons[1]) {
1284         Uint8 data = packet->rgucButtons[1];
1285         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
1286         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
1287         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
1288         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
1289         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
1290         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
1291     }
1292 
1293     if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
1294         SDL_bool dpad_up = SDL_FALSE;
1295         SDL_bool dpad_down = SDL_FALSE;
1296         SDL_bool dpad_left = SDL_FALSE;
1297         SDL_bool dpad_right = SDL_FALSE;
1298 
1299         switch (packet->ucStickHat) {
1300         case 0:
1301             dpad_up = SDL_TRUE;
1302             break;
1303         case 1:
1304             dpad_up = SDL_TRUE;
1305             dpad_right = SDL_TRUE;
1306             break;
1307         case 2:
1308             dpad_right = SDL_TRUE;
1309             break;
1310         case 3:
1311             dpad_right = SDL_TRUE;
1312             dpad_down = SDL_TRUE;
1313             break;
1314         case 4:
1315             dpad_down = SDL_TRUE;
1316             break;
1317         case 5:
1318             dpad_left = SDL_TRUE;
1319             dpad_down = SDL_TRUE;
1320             break;
1321         case 6:
1322             dpad_left = SDL_TRUE;
1323             break;
1324         case 7:
1325             dpad_up = SDL_TRUE;
1326             dpad_left = SDL_TRUE;
1327             break;
1328         default:
1329             break;
1330         }
1331         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
1332         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
1333         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
1334         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
1335     }
1336 
1337     axis = ApplyStickCalibrationCentered(ctx, 0, 0, packet->sJoystickLeft[0], (Sint16)usJoystickCenter);
1338     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
1339 
1340     axis = ApplyStickCalibrationCentered(ctx, 0, 1, packet->sJoystickLeft[1], (Sint16)usJoystickCenter);
1341     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
1342 
1343     axis = ApplyStickCalibrationCentered(ctx, 1, 0, packet->sJoystickRight[0], (Sint16)usJoystickCenter);
1344     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
1345 
1346     axis = ApplyStickCalibrationCentered(ctx, 1, 1, packet->sJoystickRight[1], (Sint16)usJoystickCenter);
1347     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
1348 
1349     ctx->m_lastSimpleState = *packet;
1350 }
1351 
SendSensorUpdate(SDL_Joystick * joystick,SDL_DriverSwitch_Context * ctx,SDL_SensorType type,Sint16 * values)1352 static void SendSensorUpdate(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SDL_SensorType type, Sint16 *values)
1353 {
1354     float data[3];
1355 
1356     /* Note the order of components has been shuffled to match PlayStation controllers,
1357      * since that's our de facto standard from already supporting those controllers, and
1358      * users will want consistent axis mappings across devices.
1359      */
1360     if (type == SDL_SENSOR_GYRO) {
1361         data[0] = -HIDAPI_DriverSwitch_ScaleGyro(values[1]);
1362         data[1] = HIDAPI_DriverSwitch_ScaleGyro(values[2]);
1363         data[2] = -HIDAPI_DriverSwitch_ScaleGyro(values[0]);
1364     } else {
1365         data[0] = -HIDAPI_DriverSwitch_ScaleAccel(values[1]);
1366         data[1] = HIDAPI_DriverSwitch_ScaleAccel(values[2]);
1367         data[2] = -HIDAPI_DriverSwitch_ScaleAccel(values[0]);
1368     }
1369 
1370     /* Right Joy-Con flips some axes, so let's flip them back for consistency */
1371     if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
1372         data[0] = -data[0];
1373         data[1] = -data[1];
1374     }
1375 
1376     SDL_PrivateJoystickSensor(joystick, type, data, 3);
1377 }
1378 
HandleFullControllerState(SDL_Joystick * joystick,SDL_DriverSwitch_Context * ctx,SwitchStatePacket_t * packet)1379 static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
1380 {
1381     Sint16 axis;
1382 
1383     if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
1384         Uint8 data = packet->controllerState.rgucButtons[0];
1385         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
1386         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
1387         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
1388         SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
1389         if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
1390             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE1, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
1391             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE3, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
1392         }
1393         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
1394         axis = (data & 0x80) ? 32767 : -32768;
1395         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
1396     }
1397 
1398     if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
1399         Uint8 data = packet->controllerState.rgucButtons[1];
1400         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
1401         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
1402         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
1403         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
1404 
1405         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
1406         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
1407     }
1408 
1409     if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
1410         Uint8 data = packet->controllerState.rgucButtons[2];
1411         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
1412         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
1413         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
1414         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
1415         if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
1416             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE4, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
1417             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE2, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
1418         }
1419         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
1420         axis = (data & 0x80) ? 32767 : -32768;
1421         SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
1422     }
1423 
1424     axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
1425     axis = ApplyStickCalibration(ctx, 0, 0, axis);
1426     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
1427 
1428     axis = ((packet->controllerState.rgucJoystickLeft[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickLeft[2] << 4);
1429     axis = ApplyStickCalibration(ctx, 0, 1, axis);
1430     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~axis);
1431 
1432     axis = packet->controllerState.rgucJoystickRight[0] | ((packet->controllerState.rgucJoystickRight[1] & 0xF) << 8);
1433     axis = ApplyStickCalibration(ctx, 1, 0, axis);
1434     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
1435 
1436     axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
1437     axis = ApplyStickCalibration(ctx, 1, 1, axis);
1438     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~axis);
1439 
1440     /* High nibble of battery/connection byte is battery level, low nibble is connection status
1441      * LSB of connection nibble is USB/Switch connection status
1442      */
1443     if (packet->controllerState.ucBatteryAndConnection & 0x1) {
1444         joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
1445     } else {
1446         /* LSB of the battery nibble is used to report charging.
1447          * The battery level is reported from 0(empty)-8(full)
1448          */
1449         int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4;
1450         if (level == 0) {
1451             joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
1452         } else if (level <= 2) {
1453             joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
1454         } else if (level <= 6) {
1455             joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
1456         } else {
1457             joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
1458         }
1459     }
1460 
1461     if (ctx->m_bReportSensors) {
1462         SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[2].sGyroX);
1463         SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[1].sGyroX);
1464         SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[0].sGyroX);
1465 
1466         SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[2].sAccelX);
1467         SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[1].sAccelX);
1468         SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[0].sAccelX);
1469     }
1470 
1471     ctx->m_lastFullState = *packet;
1472 }
1473 
1474 static SDL_bool
HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device * device)1475 HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
1476 {
1477     SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
1478     SDL_Joystick *joystick = NULL;
1479     int size;
1480 
1481     if (device->num_joysticks > 0) {
1482         joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
1483     }
1484     if (!joystick) {
1485         return SDL_FALSE;
1486     }
1487 
1488     while ((size = ReadInput(ctx)) > 0) {
1489 #ifdef DEBUG_SWITCH_PROTOCOL
1490         HIDAPI_DumpPacket("Nintendo Switch packet: size = %d", ctx->m_rgucReadBuffer, size);
1491 #endif
1492         if (ctx->m_bInputOnly) {
1493             HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]);
1494         } else {
1495             switch (ctx->m_rgucReadBuffer[0]) {
1496             case k_eSwitchInputReportIDs_SimpleControllerState:
1497                 HandleSimpleControllerState(joystick, ctx, (SwitchSimpleStatePacket_t *)&ctx->m_rgucReadBuffer[1]);
1498                 break;
1499             case k_eSwitchInputReportIDs_FullControllerState:
1500                 HandleFullControllerState(joystick, ctx, (SwitchStatePacket_t *)&ctx->m_rgucReadBuffer[1]);
1501                 break;
1502             default:
1503                 break;
1504             }
1505         }
1506     }
1507 
1508     if (ctx->m_bRumblePending || ctx->m_bRumbleZeroPending) {
1509         HIDAPI_DriverSwitch_SendPendingRumble(ctx);
1510     } else if (ctx->m_bRumbleActive &&
1511                SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_unRumbleSent + RUMBLE_REFRESH_FREQUENCY_MS)) {
1512 #ifdef DEBUG_RUMBLE
1513         SDL_Log("Sent continuing rumble, %d ms after previous rumble\n", SDL_GetTicks() - ctx->m_unRumbleSent);
1514 #endif
1515         WriteRumble(ctx);
1516     }
1517 
1518     if (size < 0) {
1519         /* Read error, device is disconnected */
1520         HIDAPI_JoystickDisconnected(device, joystick->instance_id);
1521     }
1522     return (size >= 0);
1523 }
1524 
1525 static void
HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)1526 HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1527 {
1528     SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
1529 
1530     if (!ctx->m_bInputOnly) {
1531         /* Restore simple input mode for other applications */
1532         SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
1533     }
1534 
1535     SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
1536                         SDL_GameControllerButtonReportingHintChanged, ctx);
1537 
1538     SDL_LockMutex(device->dev_lock);
1539     {
1540         SDL_hid_close(device->dev);
1541         device->dev = NULL;
1542 
1543         SDL_free(device->context);
1544         device->context = NULL;
1545     }
1546     SDL_UnlockMutex(device->dev_lock);
1547 }
1548 
1549 static void
HIDAPI_DriverSwitch_FreeDevice(SDL_HIDAPI_Device * device)1550 HIDAPI_DriverSwitch_FreeDevice(SDL_HIDAPI_Device *device)
1551 {
1552 }
1553 
1554 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
1555 {
1556     SDL_HINT_JOYSTICK_HIDAPI_SWITCH,
1557     SDL_TRUE,
1558     SDL_TRUE,
1559     HIDAPI_DriverSwitch_IsSupportedDevice,
1560     HIDAPI_DriverSwitch_GetDeviceName,
1561     HIDAPI_DriverSwitch_InitDevice,
1562     HIDAPI_DriverSwitch_GetDevicePlayerIndex,
1563     HIDAPI_DriverSwitch_SetDevicePlayerIndex,
1564     HIDAPI_DriverSwitch_UpdateDevice,
1565     HIDAPI_DriverSwitch_OpenJoystick,
1566     HIDAPI_DriverSwitch_RumbleJoystick,
1567     HIDAPI_DriverSwitch_RumbleJoystickTriggers,
1568     HIDAPI_DriverSwitch_GetJoystickCapabilities,
1569     HIDAPI_DriverSwitch_SetJoystickLED,
1570     HIDAPI_DriverSwitch_SendJoystickEffect,
1571     HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,
1572     HIDAPI_DriverSwitch_CloseJoystick,
1573     HIDAPI_DriverSwitch_FreeDevice,
1574 };
1575 
1576 #endif /* SDL_JOYSTICK_HIDAPI_SWITCH */
1577 
1578 #endif /* SDL_JOYSTICK_HIDAPI */
1579 
1580 /* vi: set ts=4 sw=4 expandtab: */
1581