hidapi: Add support for Wii U/Switch USB GameCube controller adapter.
Note that a single USB device is responsible for all 4 joysticks, so a large
rewrite of the DeviceDriver functions was necessary to allow a single device to
produce multiple joysticks.
1.1 --- a/include/SDL_hints.h Sat Mar 16 17:47:59 2019 -0700
1.2 +++ b/include/SDL_hints.h Tue Mar 12 20:27:54 2019 -0400
1.3 @@ -556,6 +556,17 @@
1.4 #define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
1.5
1.6 /**
1.7 + * \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
1.8 + *
1.9 + * This variable can be set to the following values:
1.10 + * "0" - HIDAPI driver is not used
1.11 + * "1" - HIDAPI driver is used
1.12 + *
1.13 + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
1.14 + */
1.15 +#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE"
1.16 +
1.17 +/**
1.18 * \brief A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
1.19 *
1.20 * The variable can be set to the following values:
2.1 --- a/src/joystick/SDL_gamecontrollerdb.h Sat Mar 16 17:47:59 2019 -0700
2.2 +++ b/src/joystick/SDL_gamecontrollerdb.h Tue Mar 12 20:27:54 2019 -0400
2.3 @@ -564,6 +564,7 @@
2.4 "03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,",
2.5 "030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,",
2.6 "03000000d80400008200000003000000,IMS PCU#0 Gamepad Interface,platform:Linux,a:b1,b:b0,x:b3,y:b2,back:b4,start:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,",
2.7 + "030000007e0500003703000000016800,Nintendo GameCube Controller,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b8,rightshoulder:b9,dpup:b7,dpdown:b6,dpleft:b4,dpright:b5,leftx:a0,lefty:a1~,rightx:a2,righty:a3~,lefttrigger:a4,righttrigger:a5,",
2.8 #endif
2.9 #if defined(__ANDROID__)
2.10 "05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,",
3.1 --- a/src/joystick/SDL_joystick.c Sat Mar 16 17:47:59 2019 -0700
3.2 +++ b/src/joystick/SDL_joystick.c Tue Mar 12 20:27:54 2019 -0400
3.3 @@ -1033,6 +1033,11 @@
3.4 /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
3.5 SDL_UnlockJoysticks();
3.6
3.7 + /* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
3.8 +#ifdef SDL_JOYSTICK_HIDAPI
3.9 + SDL_HIDAPI_UpdateDevices();
3.10 +#endif /* SDL_JOYSTICK_HIDAPI */
3.11 +
3.12 for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
3.13 if (joystick->attached) {
3.14 joystick->driver->Update(joystick);
3.15 @@ -1188,6 +1193,12 @@
3.16 }
3.17
3.18 SDL_bool
3.19 +SDL_IsJoystickGameCube(Uint16 vendor, Uint16 product)
3.20 +{
3.21 + return (GuessControllerType(vendor, product) == k_eControllerType_GameCube);
3.22 +}
3.23 +
3.24 +SDL_bool
3.25 SDL_IsJoystickXInput(SDL_JoystickGUID guid)
3.26 {
3.27 return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE;
4.1 --- a/src/joystick/SDL_joystick_c.h Sat Mar 16 17:47:59 2019 -0700
4.2 +++ b/src/joystick/SDL_joystick_c.h Tue Mar 12 20:27:54 2019 -0400
4.3 @@ -66,6 +66,9 @@
4.4 /* Function to return whether a joystick is an Xbox One controller */
4.5 extern SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id);
4.6
4.7 +/* Function to return whether a joystick is a GameCube controller */
4.8 +extern SDL_bool SDL_IsJoystickGameCube(Uint16 vendor_id, Uint16 product_id);
4.9 +
4.10 /* Function to return whether a joystick guid comes from the XInput driver */
4.11 extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid);
4.12
5.1 --- a/src/joystick/SDL_sysjoystick.h Sat Mar 16 17:47:59 2019 -0700
5.2 +++ b/src/joystick/SDL_sysjoystick.h Tue Mar 12 20:27:54 2019 -0400
5.3 @@ -152,6 +152,9 @@
5.4 extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
5.5 extern SDL_JoystickDriver SDL_WINDOWS_JoystickDriver;
5.6
5.7 +/* Special function to update HIDAPI devices */
5.8 +extern void SDL_HIDAPI_UpdateDevices(void);
5.9 +
5.10 #endif /* SDL_sysjoystick_h_ */
5.11
5.12 /* vi: set ts=4 sw=4 expandtab: */
6.1 --- a/src/joystick/controller_type.h Sat Mar 16 17:47:59 2019 -0700
6.2 +++ b/src/joystick/controller_type.h Tue Mar 12 20:27:54 2019 -0400
6.3 @@ -57,6 +57,7 @@
6.4 k_eControllerType_SwitchJoyConPair = 41,
6.5 k_eControllerType_SwitchInputOnlyController = 42,
6.6 k_eControllerType_MobileTouch = 43,
6.7 + k_eControllerType_GameCube = 44,
6.8 k_eControllerType_LastController, // Don't add game controllers below this enumeration - this enumeration can change value
6.9
6.10 // Keyboards and Mice
6.11 @@ -387,6 +388,8 @@
6.12 { MAKE_CONTROLLER_ID( 0x20d6, 0xa711 ), k_eControllerType_SwitchInputOnlyController }, // PowerA Wired Controller Plus
6.13 { MAKE_CONTROLLER_ID( 0x0f0d, 0x0092 ), k_eControllerType_SwitchInputOnlyController }, // HORI Pokken Tournament DX Pro Pad
6.14
6.15 + { MAKE_CONTROLLER_ID( 0x057e, 0x0337 ), k_eControllerType_GameCube }, // Nintendo Wii U/Switch GameCube USB Adapter
6.16 +
6.17
6.18 // Valve products - don't add to public list
6.19 { MAKE_CONTROLLER_ID( 0x0000, 0x11fb ), k_eControllerType_MobileTouch }, // Streaming mobile touch virtual controls
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c Tue Mar 12 20:27:54 2019 -0400
7.3 @@ -0,0 +1,339 @@
7.4 +/*
7.5 + Simple DirectMedia Layer
7.6 + Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
7.7 +
7.8 + This software is provided 'as-is', without any express or implied
7.9 + warranty. In no event will the authors be held liable for any damages
7.10 + arising from the use of this software.
7.11 +
7.12 + Permission is granted to anyone to use this software for any purpose,
7.13 + including commercial applications, and to alter it and redistribute it
7.14 + freely, subject to the following restrictions:
7.15 +
7.16 + 1. The origin of this software must not be misrepresented; you must not
7.17 + claim that you wrote the original software. If you use this software
7.18 + in a product, an acknowledgment in the product documentation would be
7.19 + appreciated but is not required.
7.20 + 2. Altered source versions must be plainly marked as such, and must not be
7.21 + misrepresented as being the original software.
7.22 + 3. This notice may not be removed or altered from any source distribution.
7.23 +*/
7.24 +#include "../../SDL_internal.h"
7.25 +
7.26 +#ifdef SDL_JOYSTICK_HIDAPI
7.27 +
7.28 +#include "SDL_hints.h"
7.29 +#include "SDL_log.h"
7.30 +#include "SDL_events.h"
7.31 +#include "SDL_timer.h"
7.32 +#include "SDL_haptic.h"
7.33 +#include "SDL_joystick.h"
7.34 +#include "SDL_gamecontroller.h"
7.35 +#include "../SDL_sysjoystick.h"
7.36 +#include "SDL_hidapijoystick_c.h"
7.37 +
7.38 +
7.39 +#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
7.40 +
7.41 +typedef struct {
7.42 + SDL_JoystickID joysticks[4];
7.43 + Uint8 rumble[5];
7.44 + Uint32 rumbleExpiration[4];
7.45 + /* Without this variable, hid_write starts to lag a TON */
7.46 + Uint8 rumbleUpdate;
7.47 +} SDL_DriverGameCube_Context;
7.48 +
7.49 +static SDL_bool
7.50 +HIDAPI_DriverGameCube_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number)
7.51 +{
7.52 + return SDL_IsJoystickGameCube(vendor_id, product_id);
7.53 +}
7.54 +
7.55 +static const char *
7.56 +HIDAPI_DriverGameCube_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
7.57 +{
7.58 + /* Give a user friendly name for this controller */
7.59 + if (SDL_IsJoystickGameCube(vendor_id, product_id)) {
7.60 + return "Nintendo GameCube Controller";
7.61 + }
7.62 + return NULL;
7.63 +}
7.64 +
7.65 +static SDL_bool
7.66 +HIDAPI_DriverGameCube_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
7.67 +{
7.68 + SDL_DriverGameCube_Context *ctx;
7.69 + Uint8 packet[37];
7.70 + Uint8 *curSlot;
7.71 + Uint8 i;
7.72 + int size;
7.73 + Uint8 initMagic = 0x13;
7.74 + Uint8 rumbleMagic = 0x11;
7.75 +
7.76 + ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
7.77 + if (!ctx) {
7.78 + SDL_OutOfMemory();
7.79 + return SDL_FALSE;
7.80 + }
7.81 + ctx->joysticks[0] = -1;
7.82 + ctx->joysticks[1] = -1;
7.83 + ctx->joysticks[2] = -1;
7.84 + ctx->joysticks[3] = -1;
7.85 + ctx->rumble[0] = rumbleMagic;
7.86 +
7.87 + context->context = ctx;
7.88 +
7.89 + /* This is all that's needed to initialize the device. Really! */
7.90 + if (hid_write(context->device, &initMagic, sizeof(initMagic)) <= 0) {
7.91 + SDL_SetError("Couldn't initialize WUP-028");
7.92 + SDL_free(ctx);
7.93 + return SDL_FALSE;
7.94 + }
7.95 +
7.96 + /* Add all the applicable joysticks */
7.97 + while ((size = hid_read_timeout(context->device, packet, sizeof(packet), 0)) > 0) {
7.98 + if (size < 37 || packet[0] != 0x21) {
7.99 + continue; /* Nothing to do yet...? */
7.100 + }
7.101 +
7.102 + /* Go through all 4 slots */
7.103 + curSlot = packet + 1;
7.104 + for (i = 0; i < 4; i += 1, curSlot += 9) {
7.105 + if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
7.106 + if (ctx->joysticks[i] == -1) {
7.107 + ctx->joysticks[i] = SDL_GetNextJoystickInstanceID();
7.108 +
7.109 + *num_joysticks += 1;
7.110 +
7.111 + SDL_PrivateJoystickAdded(ctx->joysticks[i]);
7.112 + }
7.113 + } else {
7.114 + if (ctx->joysticks[i] != -1) {
7.115 + SDL_PrivateJoystickRemoved(ctx->joysticks[i]);
7.116 +
7.117 + *num_joysticks -= 1;
7.118 +
7.119 + ctx->joysticks[i] = -1;
7.120 + }
7.121 + continue;
7.122 + }
7.123 + }
7.124 + }
7.125 +
7.126 + return SDL_TRUE;
7.127 +}
7.128 +
7.129 +static void
7.130 +HIDAPI_DriverGameCube_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
7.131 +{
7.132 + SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
7.133 + Uint8 i;
7.134 +
7.135 + /* Stop all rumble activity */
7.136 + for (i = 1; i < 5; i += 1) {
7.137 + ctx->rumble[i] = 0;
7.138 + }
7.139 + hid_write(context->device, ctx->rumble, sizeof(ctx->rumble));
7.140 +
7.141 + /* Remove all joysticks! */
7.142 + for (i = 0; i < 4; i += 1) {
7.143 + if (ctx->joysticks[i] != -1) {
7.144 + *num_joysticks -= 1;
7.145 + if (send_event) {
7.146 + SDL_PrivateJoystickRemoved(ctx->joysticks[i]);
7.147 + }
7.148 + }
7.149 + }
7.150 +
7.151 + SDL_free(context->context);
7.152 +}
7.153 +
7.154 +static SDL_bool
7.155 +HIDAPI_DriverGameCube_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
7.156 +{
7.157 + SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
7.158 + SDL_Joystick *joystick;
7.159 + Uint8 packet[37];
7.160 + Uint8 *curSlot;
7.161 + Uint32 now;
7.162 + Uint8 i;
7.163 + int size;
7.164 +
7.165 + /* Read input packet */
7.166 + while ((size = hid_read_timeout(context->device, packet, sizeof(packet), 0)) > 0) {
7.167 + if (size < 37 || packet[0] != 0x21) {
7.168 + continue; /* Nothing to do right now...? */
7.169 + }
7.170 +
7.171 + /* Go through all 4 slots */
7.172 + curSlot = packet + 1;
7.173 + for (i = 0; i < 4; i += 1, curSlot += 9) {
7.174 + if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
7.175 + if (ctx->joysticks[i] == -1) {
7.176 + ctx->joysticks[i] = SDL_GetNextJoystickInstanceID();
7.177 +
7.178 + *num_joysticks += 1;
7.179 +
7.180 + SDL_PrivateJoystickAdded(ctx->joysticks[i]);
7.181 + }
7.182 + joystick = SDL_JoystickFromInstanceID(ctx->joysticks[i]);
7.183 +
7.184 + /* Hasn't been opened yet, skip */
7.185 + if (joystick == NULL) {
7.186 + continue;
7.187 + }
7.188 + } else {
7.189 + if (ctx->joysticks[i] != -1) {
7.190 + SDL_PrivateJoystickRemoved(ctx->joysticks[i]);
7.191 +
7.192 + *num_joysticks -= 1;
7.193 +
7.194 + ctx->joysticks[i] = -1;
7.195 + }
7.196 + continue;
7.197 + }
7.198 +
7.199 + #define READ_BUTTON(off, flag, button) \
7.200 + SDL_PrivateJoystickButton( \
7.201 + joystick, \
7.202 + button, \
7.203 + (curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED \
7.204 + );
7.205 + READ_BUTTON(1, 0x01, 0) /* A */
7.206 + READ_BUTTON(1, 0x02, 1) /* B */
7.207 + READ_BUTTON(1, 0x04, 2) /* X */
7.208 + READ_BUTTON(1, 0x08, 3) /* Y */
7.209 + READ_BUTTON(1, 0x10, 4) /* DPAD_LEFT */
7.210 + READ_BUTTON(1, 0x20, 5) /* DPAD_RIGHT */
7.211 + READ_BUTTON(1, 0x40, 6) /* DPAD_DOWN */
7.212 + READ_BUTTON(1, 0x80, 7) /* DPAD_UP */
7.213 + READ_BUTTON(2, 0x01, 8) /* START */
7.214 + READ_BUTTON(2, 0x02, 9) /* RIGHTSHOULDER */
7.215 + /* [2] 0x04 - R, [2] 0x08 - L */
7.216 + #undef READ_BUTTON
7.217 +
7.218 + /* Axis math taken from SDL_xinputjoystick.c */
7.219 + #define READ_AXIS(off, axis) \
7.220 + SDL_PrivateJoystickAxis( \
7.221 + joystick, \
7.222 + axis, \
7.223 + (Sint16)(((int)curSlot[off] * 257) - 32768) \
7.224 + );
7.225 + READ_AXIS(3, 0) /* LEFTX */
7.226 + READ_AXIS(4, 1) /* LEFTY */
7.227 + READ_AXIS(5, 2) /* RIGHTX */
7.228 + READ_AXIS(6, 3) /* RIGHTY */
7.229 + READ_AXIS(7, 4) /* TRIGGERLEFT */
7.230 + READ_AXIS(8, 5) /* TRIGGERRIGHT */
7.231 + #undef READ_AXIS
7.232 + }
7.233 + }
7.234 +
7.235 + /* Write rumble packet */
7.236 + now = SDL_GetTicks();
7.237 + for (i = 0; i < 4; i += 1) {
7.238 + if (ctx->rumbleExpiration[i] > 0) {
7.239 + if (SDL_TICKS_PASSED(now, ctx->rumbleExpiration[i])) {
7.240 + ctx->rumble[i + 1] = 0;
7.241 + ctx->rumbleExpiration[i] = 0;
7.242 + ctx->rumbleUpdate = 1;
7.243 + }
7.244 + }
7.245 + }
7.246 + if (ctx->rumbleUpdate) {
7.247 + hid_write(context->device, ctx->rumble, sizeof(ctx->rumble));
7.248 + ctx->rumbleUpdate = 0;
7.249 + }
7.250 +
7.251 + /* If we got here, nothing bad happened! */
7.252 + return SDL_TRUE;
7.253 +}
7.254 +
7.255 +static int
7.256 +HIDAPI_DriverGameCube_NumJoysticks(SDL_HIDAPI_DriverData *context)
7.257 +{
7.258 + SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
7.259 + int i, joysticks = 0;
7.260 + for (i = 0; i < 4; i += 1) {
7.261 + if (ctx->joysticks[i] != -1) {
7.262 + joysticks += 1;
7.263 + }
7.264 + }
7.265 + return joysticks;
7.266 +}
7.267 +
7.268 +static SDL_JoystickID
7.269 +HIDAPI_DriverGameCube_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
7.270 +{
7.271 + SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
7.272 + Uint8 i;
7.273 + for (i = 0; i < 4; i += 1) {
7.274 + if (ctx->joysticks[i] != -1) {
7.275 + if (index == 0) {
7.276 + return ctx->joysticks[i];
7.277 + }
7.278 + index -= 1;
7.279 + }
7.280 + }
7.281 + return -1; /* Should never get here! */
7.282 +}
7.283 +
7.284 +static SDL_bool
7.285 +HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
7.286 +{
7.287 + SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
7.288 + SDL_JoystickID instance = SDL_JoystickInstanceID(joystick);
7.289 + Uint8 i;
7.290 + for (i = 0; i < 4; i += 1) {
7.291 + if (instance == ctx->joysticks[i]) {
7.292 + joystick->nbuttons = 10;
7.293 + joystick->naxes = 6;
7.294 + joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
7.295 + return SDL_TRUE;
7.296 + }
7.297 + }
7.298 + return SDL_FALSE; /* Should never get here! */
7.299 +}
7.300 +
7.301 +static int
7.302 +HIDAPI_DriverGameCube_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
7.303 +{
7.304 + SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
7.305 + SDL_JoystickID instance = SDL_JoystickInstanceID(joystick);
7.306 + Uint8 i, val;
7.307 + for (i = 0; i < 4; i += 1) {
7.308 + if (instance == ctx->joysticks[i]) {
7.309 + val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
7.310 + if (val != ctx->rumble[i + 1]) {
7.311 + ctx->rumble[i + 1] = val;
7.312 + ctx->rumbleUpdate = 1;
7.313 + }
7.314 + if (val && duration_ms < SDL_HAPTIC_INFINITY) {
7.315 + ctx->rumbleExpiration[i] = SDL_GetTicks() + duration_ms;
7.316 + } else {
7.317 + ctx->rumbleExpiration[i] = 0;
7.318 + }
7.319 + return 0;
7.320 + }
7.321 + }
7.322 + return -1;
7.323 +}
7.324 +
7.325 +SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
7.326 +{
7.327 + SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
7.328 + SDL_TRUE,
7.329 + HIDAPI_DriverGameCube_IsSupportedDevice,
7.330 + HIDAPI_DriverGameCube_GetDeviceName,
7.331 + HIDAPI_DriverGameCube_InitDriver,
7.332 + HIDAPI_DriverGameCube_QuitDriver,
7.333 + HIDAPI_DriverGameCube_UpdateDriver,
7.334 + HIDAPI_DriverGameCube_NumJoysticks,
7.335 + HIDAPI_DriverGameCube_InstanceIDForIndex,
7.336 + HIDAPI_DriverGameCube_OpenJoystick,
7.337 + HIDAPI_DriverGameCube_Rumble
7.338 +};
7.339 +
7.340 +#endif /* SDL_JOYSTICK_HIDAPI_GAMECUBE */
7.341 +
7.342 +#endif /* SDL_JOYSTICK_HIDAPI */
8.1 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c Sat Mar 16 17:47:59 2019 -0700
8.2 +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c Tue Mar 12 20:27:54 2019 -0400
8.3 @@ -108,6 +108,7 @@
8.4 } DS4EffectsState_t;
8.5
8.6 typedef struct {
8.7 + SDL_JoystickID joystickID;
8.8 SDL_bool is_dongle;
8.9 SDL_bool is_bluetooth;
8.10 SDL_bool audio_supported;
8.11 @@ -272,10 +273,8 @@
8.12 return SDL_TRUE;
8.13 }
8.14
8.15 -static int HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
8.16 -
8.17 static SDL_bool
8.18 -HIDAPI_DriverPS4_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
8.19 +HIDAPI_DriverPS4_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
8.20 {
8.21 SDL_DriverPS4_Context *ctx;
8.22
8.23 @@ -284,14 +283,14 @@
8.24 SDL_OutOfMemory();
8.25 return SDL_FALSE;
8.26 }
8.27 - *context = ctx;
8.28 + context->context = ctx;
8.29
8.30 /* Check for type of connection */
8.31 ctx->is_dongle = (vendor_id == SONY_USB_VID && product_id == SONY_DS4_DONGLE_PID);
8.32 if (ctx->is_dongle) {
8.33 ctx->is_bluetooth = SDL_FALSE;
8.34 } else if (vendor_id == SONY_USB_VID) {
8.35 - ctx->is_bluetooth = !CheckUSBConnected(dev);
8.36 + ctx->is_bluetooth = !CheckUSBConnected(context->device);
8.37 } else {
8.38 /* Third party controllers appear to all be wired */
8.39 ctx->is_bluetooth = SDL_FALSE;
8.40 @@ -314,8 +313,45 @@
8.41 }
8.42 }
8.43
8.44 + ctx->joystickID = SDL_GetNextJoystickInstanceID();
8.45 + *num_joysticks += 1;
8.46 + SDL_PrivateJoystickAdded(ctx->joystickID);
8.47 +
8.48 + return SDL_TRUE;
8.49 +}
8.50 +
8.51 +static void
8.52 +HIDAPI_DriverPS4_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
8.53 +{
8.54 + SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
8.55 +
8.56 + *num_joysticks -= 1;
8.57 + if (send_event) {
8.58 + SDL_PrivateJoystickRemoved(ctx->joystickID);
8.59 + }
8.60 + SDL_free(context->context);
8.61 +}
8.62 +
8.63 +static int
8.64 +HIDAPI_DriverPS4_NumJoysticks(SDL_HIDAPI_DriverData *context)
8.65 +{
8.66 + return 1;
8.67 +}
8.68 +
8.69 +static SDL_JoystickID
8.70 +HIDAPI_DriverPS4_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
8.71 +{
8.72 + SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
8.73 + return ctx->joystickID;
8.74 +}
8.75 +
8.76 +static int HIDAPI_DriverPS4_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
8.77 +
8.78 +static SDL_bool
8.79 +HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
8.80 +{
8.81 /* Initialize LED and effect state */
8.82 - HIDAPI_DriverPS4_Rumble(joystick, dev, ctx, 0, 0, 0);
8.83 + HIDAPI_DriverPS4_Rumble(context, joystick, 0, 0, 0);
8.84
8.85 /* Initialize the joystick capabilities */
8.86 joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
8.87 @@ -326,9 +362,9 @@
8.88 }
8.89
8.90 static int
8.91 -HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
8.92 +HIDAPI_DriverPS4_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
8.93 {
8.94 - SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context;
8.95 + SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
8.96 DS4EffectsState_t *effects;
8.97 Uint8 data[78];
8.98 int report_size, offset;
8.99 @@ -386,7 +422,7 @@
8.100 SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
8.101 }
8.102
8.103 - if (hid_write(dev, data, report_size) != report_size) {
8.104 + if (hid_write(context->device, data, report_size) != report_size) {
8.105 return SDL_SetError("Couldn't send rumble packet");
8.106 }
8.107
8.108 @@ -508,20 +544,25 @@
8.109 }
8.110
8.111 static SDL_bool
8.112 -HIDAPI_DriverPS4_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
8.113 +HIDAPI_DriverPS4_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
8.114 {
8.115 - SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context;
8.116 + SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
8.117 + SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
8.118 Uint8 data[USB_PACKET_LENGTH];
8.119 int size;
8.120
8.121 - while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
8.122 + if (joystick == NULL) {
8.123 + return SDL_TRUE; /* Nothing to do right now! */
8.124 + }
8.125 +
8.126 + while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
8.127 switch (data[0]) {
8.128 case k_EPS4ReportIdUsbState:
8.129 - HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[1]);
8.130 + HIDAPI_DriverPS4_HandleStatePacket(joystick, context->device, ctx, (PS4StatePacket_t *)&data[1]);
8.131 break;
8.132 case k_EPS4ReportIdBluetoothState:
8.133 /* Bluetooth state packets have two additional bytes at the beginning */
8.134 - HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[3]);
8.135 + HIDAPI_DriverPS4_HandleStatePacket(joystick, context->device, ctx, (PS4StatePacket_t *)&data[3]);
8.136 break;
8.137 default:
8.138 #ifdef DEBUG_JOYSTICK
8.139 @@ -534,29 +575,26 @@
8.140 if (ctx->rumble_expiration) {
8.141 Uint32 now = SDL_GetTicks();
8.142 if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
8.143 - HIDAPI_DriverPS4_Rumble(joystick, dev, context, 0, 0, 0);
8.144 + HIDAPI_DriverPS4_Rumble(context, joystick, 0, 0, 0);
8.145 }
8.146 }
8.147
8.148 return (size >= 0);
8.149 }
8.150
8.151 -static void
8.152 -HIDAPI_DriverPS4_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
8.153 -{
8.154 - SDL_free(context);
8.155 -}
8.156 -
8.157 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
8.158 {
8.159 SDL_HINT_JOYSTICK_HIDAPI_PS4,
8.160 SDL_TRUE,
8.161 HIDAPI_DriverPS4_IsSupportedDevice,
8.162 HIDAPI_DriverPS4_GetDeviceName,
8.163 - HIDAPI_DriverPS4_Init,
8.164 - HIDAPI_DriverPS4_Rumble,
8.165 - HIDAPI_DriverPS4_Update,
8.166 - HIDAPI_DriverPS4_Quit
8.167 + HIDAPI_DriverPS4_InitDriver,
8.168 + HIDAPI_DriverPS4_QuitDriver,
8.169 + HIDAPI_DriverPS4_UpdateDriver,
8.170 + HIDAPI_DriverPS4_NumJoysticks,
8.171 + HIDAPI_DriverPS4_InstanceIDForIndex,
8.172 + HIDAPI_DriverPS4_OpenJoystick,
8.173 + HIDAPI_DriverPS4_Rumble
8.174 };
8.175
8.176 #endif /* SDL_JOYSTICK_HIDAPI_PS4 */
9.1 --- a/src/joystick/hidapi/SDL_hidapi_switch.c Sat Mar 16 17:47:59 2019 -0700
9.2 +++ b/src/joystick/hidapi/SDL_hidapi_switch.c Tue Mar 12 20:27:54 2019 -0400
9.3 @@ -183,6 +183,7 @@
9.4 #pragma pack()
9.5
9.6 typedef struct {
9.7 + SDL_JoystickID joystickID;
9.8 hid_device *dev;
9.9 SDL_bool m_bIsUsingBluetooth;
9.10 Uint8 m_nCommandNumber;
9.11 @@ -570,7 +571,7 @@
9.12 }
9.13
9.14 static SDL_bool
9.15 -HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
9.16 +HIDAPI_DriverSwitch_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
9.17 {
9.18 SDL_DriverSwitch_Context *ctx;
9.19 Uint8 input_mode;
9.20 @@ -580,9 +581,9 @@
9.21 SDL_OutOfMemory();
9.22 return SDL_FALSE;
9.23 }
9.24 - ctx->dev = dev;
9.25 + ctx->dev = context->device;
9.26
9.27 - *context = ctx;
9.28 + context->context = ctx;
9.29
9.30 /* Initialize rumble data */
9.31 SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
9.32 @@ -627,6 +628,18 @@
9.33 }
9.34 }
9.35
9.36 + ctx->joystickID = SDL_GetNextJoystickInstanceID();
9.37 + *num_joysticks += 1;
9.38 + SDL_PrivateJoystickAdded(ctx->joystickID);
9.39 +
9.40 + return SDL_TRUE;
9.41 +}
9.42 +
9.43 +static SDL_bool
9.44 +HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
9.45 +{
9.46 + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
9.47 +
9.48 /* Set the LED state */
9.49 SetHomeLED(ctx, 100);
9.50 SetSlotLED(ctx, (joystick->instance_id % 4));
9.51 @@ -640,9 +653,9 @@
9.52 }
9.53
9.54 static int
9.55 -HIDAPI_DriverSwitch_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
9.56 +HIDAPI_DriverSwitch_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
9.57 {
9.58 - SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
9.59 + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
9.60
9.61 /* Experimentally determined rumble values. These will only matter on some controllers as tested ones
9.62 * seem to disregard these and just use any non-zero rumble values as a binary flag for constant rumble
9.63 @@ -847,11 +860,16 @@
9.64 }
9.65
9.66 static SDL_bool
9.67 -HIDAPI_DriverSwitch_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
9.68 +HIDAPI_DriverSwitch_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
9.69 {
9.70 - SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
9.71 + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
9.72 + SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
9.73 int size;
9.74
9.75 + if (joystick == NULL) {
9.76 + return SDL_TRUE; /* Nothing to do right now! */
9.77 + }
9.78 +
9.79 while ((size = ReadInput(ctx)) > 0) {
9.80 switch (ctx->m_rgucReadBuffer[0]) {
9.81 case k_eSwitchInputReportIDs_SimpleControllerState:
9.82 @@ -868,7 +886,7 @@
9.83 if (ctx->m_nRumbleExpiration) {
9.84 Uint32 now = SDL_GetTicks();
9.85 if (SDL_TICKS_PASSED(now, ctx->m_nRumbleExpiration)) {
9.86 - HIDAPI_DriverSwitch_Rumble(joystick, dev, context, 0, 0, 0);
9.87 + HIDAPI_DriverSwitch_Rumble(context, joystick, 0, 0, 0);
9.88 }
9.89 }
9.90
9.91 @@ -876,14 +894,31 @@
9.92 }
9.93
9.94 static void
9.95 -HIDAPI_DriverSwitch_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
9.96 +HIDAPI_DriverSwitch_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
9.97 {
9.98 - SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
9.99 + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
9.100
9.101 /* Restore simple input mode for other applications */
9.102 SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
9.103
9.104 - SDL_free(context);
9.105 + *num_joysticks -= 1;
9.106 + if (send_event) {
9.107 + SDL_PrivateJoystickRemoved(ctx->joystickID);
9.108 + }
9.109 + SDL_free(context->context);
9.110 +}
9.111 +
9.112 +static int
9.113 +HIDAPI_DriverSwitch_NumJoysticks(SDL_HIDAPI_DriverData *context)
9.114 +{
9.115 + return 1;
9.116 +}
9.117 +
9.118 +static SDL_JoystickID
9.119 +HIDAPI_DriverSwitch_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
9.120 +{
9.121 + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
9.122 + return ctx->joystickID;
9.123 }
9.124
9.125 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
9.126 @@ -892,10 +927,13 @@
9.127 SDL_TRUE,
9.128 HIDAPI_DriverSwitch_IsSupportedDevice,
9.129 HIDAPI_DriverSwitch_GetDeviceName,
9.130 - HIDAPI_DriverSwitch_Init,
9.131 - HIDAPI_DriverSwitch_Rumble,
9.132 - HIDAPI_DriverSwitch_Update,
9.133 - HIDAPI_DriverSwitch_Quit
9.134 + HIDAPI_DriverSwitch_InitDriver,
9.135 + HIDAPI_DriverSwitch_QuitDriver,
9.136 + HIDAPI_DriverSwitch_UpdateDriver,
9.137 + HIDAPI_DriverSwitch_NumJoysticks,
9.138 + HIDAPI_DriverSwitch_InstanceIDForIndex,
9.139 + HIDAPI_DriverSwitch_OpenJoystick,
9.140 + HIDAPI_DriverSwitch_Rumble
9.141 };
9.142
9.143 #endif /* SDL_JOYSTICK_HIDAPI_SWITCH */
10.1 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c Sat Mar 16 17:47:59 2019 -0700
10.2 +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c Tue Mar 12 20:27:54 2019 -0400
10.3 @@ -54,6 +54,7 @@
10.4
10.5
10.6 typedef struct {
10.7 + SDL_JoystickID joystickID;
10.8 Uint8 last_state[USB_PACKET_LENGTH];
10.9 Uint32 rumble_expiration;
10.10 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
10.11 @@ -277,7 +278,7 @@
10.12 }
10.13
10.14 static SDL_bool
10.15 -HIDAPI_DriverXbox360_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
10.16 +HIDAPI_DriverXbox360_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
10.17 {
10.18 SDL_DriverXbox360_Context *ctx;
10.19
10.20 @@ -296,10 +297,20 @@
10.21 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
10.22 HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
10.23 #endif
10.24 - *context = ctx;
10.25 + context->context = ctx;
10.26 +
10.27 + ctx->joystickID = SDL_GetNextJoystickInstanceID();
10.28 + *num_joysticks += 1;
10.29 + SDL_PrivateJoystickAdded(ctx->joystickID);
10.30
10.31 + return SDL_TRUE;
10.32 +}
10.33 +
10.34 +static SDL_bool
10.35 +HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
10.36 +{
10.37 /* Set the controller LED */
10.38 - SetSlotLED(dev, (joystick->instance_id % 4));
10.39 + SetSlotLED(context->device, (joystick->instance_id % 4));
10.40
10.41 /* Initialize the joystick capabilities */
10.42 joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
10.43 @@ -310,9 +321,22 @@
10.44 }
10.45
10.46 static int
10.47 -HIDAPI_DriverXbox360_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
10.48 +HIDAPI_DriverXbox360_NumJoysticks(SDL_HIDAPI_DriverData *context)
10.49 +{
10.50 + return 1;
10.51 +}
10.52 +
10.53 +static SDL_JoystickID
10.54 +HIDAPI_DriverXbox360_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
10.55 {
10.56 - SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
10.57 + SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
10.58 + return ctx->joystickID;
10.59 +}
10.60 +
10.61 +static int
10.62 +HIDAPI_DriverXbox360_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
10.63 +{
10.64 + SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
10.65
10.66 #ifdef __WIN32__
10.67 SDL_bool rumbled = SDL_FALSE;
10.68 @@ -365,7 +389,7 @@
10.69 rumble_packet[4] = (high_frequency_rumble >> 8);
10.70 #endif
10.71
10.72 - if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
10.73 + if (hid_write(context->device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
10.74 return SDL_SetError("Couldn't send rumble packet");
10.75 }
10.76 #endif /* __WIN32__ */
10.77 @@ -705,26 +729,31 @@
10.78 #endif /* __MACOSX__ */
10.79
10.80 static SDL_bool
10.81 -HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
10.82 +HIDAPI_DriverXbox360_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
10.83 {
10.84 - SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
10.85 + SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
10.86 + SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
10.87 Uint8 data[USB_PACKET_LENGTH];
10.88 int size;
10.89
10.90 - while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
10.91 + if (joystick == NULL) {
10.92 + return SDL_TRUE; /* Nothing to do right now! */
10.93 + }
10.94 +
10.95 + while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
10.96 #ifdef __WIN32__
10.97 - HIDAPI_DriverXbox360_HandleStatePacket(joystick, dev, ctx, data, size);
10.98 + HIDAPI_DriverXbox360_HandleStatePacket(joystick, context->device, ctx, data, size);
10.99 #else
10.100 switch (data[0]) {
10.101 case 0x00:
10.102 - HIDAPI_DriverXbox360_HandleStatePacket(joystick, dev, ctx, data, size);
10.103 + HIDAPI_DriverXbox360_HandleStatePacket(joystick, context->device, ctx, data, size);
10.104 break;
10.105 #ifdef __MACOSX__
10.106 case 0x01:
10.107 - HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, dev, ctx, data, size);
10.108 + HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, context->device, ctx, data, size);
10.109 break;
10.110 case 0x02:
10.111 - HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, dev, ctx, data, size);
10.112 + HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, context->device, ctx, data, size);
10.113 break;
10.114 #endif
10.115 default:
10.116 @@ -742,7 +771,7 @@
10.117 if (ctx->rumble_expiration) {
10.118 Uint32 now = SDL_GetTicks();
10.119 if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
10.120 - HIDAPI_DriverXbox360_Rumble(joystick, dev, context, 0, 0, 0);
10.121 + HIDAPI_DriverXbox360_Rumble(context, joystick, 0, 0, 0);
10.122 }
10.123 }
10.124
10.125 @@ -750,11 +779,9 @@
10.126 }
10.127
10.128 static void
10.129 -HIDAPI_DriverXbox360_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
10.130 +HIDAPI_DriverXbox360_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
10.131 {
10.132 -#if defined(SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT) || defined(SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT)
10.133 - SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
10.134 -#endif
10.135 + SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
10.136
10.137 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
10.138 if (ctx->xinput_enabled) {
10.139 @@ -765,7 +792,11 @@
10.140 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
10.141 HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
10.142 #endif
10.143 - SDL_free(context);
10.144 + *num_joysticks -= 1;
10.145 + if (send_event) {
10.146 + SDL_PrivateJoystickRemoved(ctx->joystickID);
10.147 + }
10.148 + SDL_free(context->context);
10.149 }
10.150
10.151 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
10.152 @@ -774,10 +805,13 @@
10.153 SDL_TRUE,
10.154 HIDAPI_DriverXbox360_IsSupportedDevice,
10.155 HIDAPI_DriverXbox360_GetDeviceName,
10.156 - HIDAPI_DriverXbox360_Init,
10.157 - HIDAPI_DriverXbox360_Rumble,
10.158 - HIDAPI_DriverXbox360_Update,
10.159 - HIDAPI_DriverXbox360_Quit
10.160 + HIDAPI_DriverXbox360_InitDriver,
10.161 + HIDAPI_DriverXbox360_QuitDriver,
10.162 + HIDAPI_DriverXbox360_UpdateDriver,
10.163 + HIDAPI_DriverXbox360_NumJoysticks,
10.164 + HIDAPI_DriverXbox360_InstanceIDForIndex,
10.165 + HIDAPI_DriverXbox360_OpenJoystick,
10.166 + HIDAPI_DriverXbox360_Rumble
10.167 };
10.168
10.169 #endif /* SDL_JOYSTICK_HIDAPI_XBOX360 */
11.1 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c Sat Mar 16 17:47:59 2019 -0700
11.2 +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c Tue Mar 12 20:27:54 2019 -0400
11.3 @@ -124,6 +124,7 @@
11.4 };
11.5
11.6 typedef struct {
11.7 + SDL_JoystickID joystickID;
11.8 Uint8 sequence;
11.9 Uint8 last_state[USB_PACKET_LENGTH];
11.10 Uint32 rumble_expiration;
11.11 @@ -143,7 +144,7 @@
11.12 }
11.13
11.14 static SDL_bool
11.15 -HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
11.16 +HIDAPI_DriverXboxOne_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
11.17 {
11.18 SDL_DriverXboxOne_Context *ctx;
11.19 int i;
11.20 @@ -154,7 +155,7 @@
11.21 SDL_OutOfMemory();
11.22 return SDL_FALSE;
11.23 }
11.24 - *context = ctx;
11.25 + context->context = ctx;
11.26
11.27 /* Send the controller init data */
11.28 for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
11.29 @@ -162,7 +163,7 @@
11.30 if (!packet->vendor_id || (vendor_id == packet->vendor_id && product_id == packet->product_id)) {
11.31 SDL_memcpy(init_packet, packet->data, packet->size);
11.32 init_packet[2] = ctx->sequence++;
11.33 - if (hid_write(dev, init_packet, packet->size) != packet->size) {
11.34 + if (hid_write(context->device, init_packet, packet->size) != packet->size) {
11.35 SDL_SetError("Couldn't write Xbox One initialization packet");
11.36 SDL_free(ctx);
11.37 return SDL_FALSE;
11.38 @@ -170,6 +171,16 @@
11.39 }
11.40 }
11.41
11.42 + ctx->joystickID = SDL_GetNextJoystickInstanceID();
11.43 + *num_joysticks += 1;
11.44 + SDL_PrivateJoystickAdded(ctx->joystickID);
11.45 +
11.46 + return SDL_TRUE;
11.47 +}
11.48 +
11.49 +static SDL_bool
11.50 +HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
11.51 +{
11.52 /* Initialize the joystick capabilities */
11.53 joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
11.54 joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
11.55 @@ -178,10 +189,35 @@
11.56 return SDL_TRUE;
11.57 }
11.58
11.59 +static void
11.60 +HIDAPI_DriverXboxOne_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
11.61 +{
11.62 + SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
11.63 +
11.64 + *num_joysticks -= 1;
11.65 + if (send_event) {
11.66 + SDL_PrivateJoystickRemoved(ctx->joystickID);
11.67 + }
11.68 + SDL_free(context->context);
11.69 +}
11.70 +
11.71 static int
11.72 -HIDAPI_DriverXboxOne_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
11.73 +HIDAPI_DriverXboxOne_NumJoysticks(SDL_HIDAPI_DriverData *context)
11.74 +{
11.75 + return 1;
11.76 +}
11.77 +
11.78 +static SDL_JoystickID
11.79 +HIDAPI_DriverXboxOne_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
11.80 {
11.81 - SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
11.82 + SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
11.83 + return ctx->joystickID;
11.84 +}
11.85 +
11.86 +static int
11.87 +HIDAPI_DriverXboxOne_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
11.88 +{
11.89 + SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
11.90 Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
11.91
11.92 /* The Rock Candy Xbox One Controller limits the range of
11.93 @@ -194,7 +230,7 @@
11.94 rumble_packet[8] = (low_frequency_rumble >> 9);
11.95 rumble_packet[9] = (high_frequency_rumble >> 9);
11.96
11.97 - if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
11.98 + if (hid_write(context->device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
11.99 return SDL_SetError("Couldn't send rumble packet");
11.100 }
11.101
11.102 @@ -267,19 +303,24 @@
11.103 }
11.104
11.105 static SDL_bool
11.106 -HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
11.107 +HIDAPI_DriverXboxOne_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
11.108 {
11.109 - SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
11.110 + SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
11.111 + SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
11.112 Uint8 data[USB_PACKET_LENGTH];
11.113 int size;
11.114
11.115 - while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
11.116 + if (joystick == NULL) {
11.117 + return SDL_TRUE; /* Nothing to do right now! */
11.118 + }
11.119 +
11.120 + while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
11.121 switch (data[0]) {
11.122 case 0x20:
11.123 - HIDAPI_DriverXboxOne_HandleStatePacket(joystick, dev, ctx, data, size);
11.124 + HIDAPI_DriverXboxOne_HandleStatePacket(joystick, context->device, ctx, data, size);
11.125 break;
11.126 case 0x07:
11.127 - HIDAPI_DriverXboxOne_HandleModePacket(joystick, dev, ctx, data, size);
11.128 + HIDAPI_DriverXboxOne_HandleModePacket(joystick, context->device, ctx, data, size);
11.129 break;
11.130 default:
11.131 #ifdef DEBUG_JOYSTICK
11.132 @@ -292,29 +333,26 @@
11.133 if (ctx->rumble_expiration) {
11.134 Uint32 now = SDL_GetTicks();
11.135 if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
11.136 - HIDAPI_DriverXboxOne_Rumble(joystick, dev, context, 0, 0, 0);
11.137 + HIDAPI_DriverXboxOne_Rumble(context, joystick, 0, 0, 0);
11.138 }
11.139 }
11.140
11.141 return (size >= 0);
11.142 }
11.143
11.144 -static void
11.145 -HIDAPI_DriverXboxOne_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
11.146 -{
11.147 - SDL_free(context);
11.148 -}
11.149 -
11.150 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
11.151 {
11.152 SDL_HINT_JOYSTICK_HIDAPI_XBOX,
11.153 SDL_TRUE,
11.154 HIDAPI_DriverXboxOne_IsSupportedDevice,
11.155 HIDAPI_DriverXboxOne_GetDeviceName,
11.156 - HIDAPI_DriverXboxOne_Init,
11.157 - HIDAPI_DriverXboxOne_Rumble,
11.158 - HIDAPI_DriverXboxOne_Update,
11.159 - HIDAPI_DriverXboxOne_Quit
11.160 + HIDAPI_DriverXboxOne_InitDriver,
11.161 + HIDAPI_DriverXboxOne_QuitDriver,
11.162 + HIDAPI_DriverXboxOne_UpdateDriver,
11.163 + HIDAPI_DriverXboxOne_NumJoysticks,
11.164 + HIDAPI_DriverXboxOne_InstanceIDForIndex,
11.165 + HIDAPI_DriverXboxOne_OpenJoystick,
11.166 + HIDAPI_DriverXboxOne_Rumble
11.167 };
11.168
11.169 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
12.1 --- a/src/joystick/hidapi/SDL_hidapijoystick.c Sat Mar 16 17:47:59 2019 -0700
12.2 +++ b/src/joystick/hidapi/SDL_hidapijoystick.c Tue Mar 12 20:27:54 2019 -0400
12.3 @@ -50,18 +50,10 @@
12.4 #endif
12.5 #endif
12.6
12.7 -struct joystick_hwdata
12.8 -{
12.9 - SDL_HIDAPI_DeviceDriver *driver;
12.10 - void *context;
12.11 -
12.12 - SDL_mutex *mutex;
12.13 - hid_device *dev;
12.14 -};
12.15 -
12.16 typedef struct _SDL_HIDAPI_Device
12.17 {
12.18 - SDL_JoystickID instance_id;
12.19 + SDL_HIDAPI_DriverData devdata;
12.20 + SDL_mutex *mutex;
12.21 char *name;
12.22 char *path;
12.23 Uint16 vendor_id;
12.24 @@ -95,6 +87,9 @@
12.25 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
12.26 &SDL_HIDAPI_DriverXboxOne,
12.27 #endif
12.28 +#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
12.29 + &SDL_HIDAPI_DriverGameCube,
12.30 +#endif
12.31 };
12.32 static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
12.33 static int SDL_HIDAPI_numjoysticks = 0;
12.34 @@ -393,6 +388,36 @@
12.35 #endif
12.36 }
12.37
12.38 +static void
12.39 +HIDAPI_InitDriver(SDL_HIDAPI_Device *device)
12.40 +{
12.41 + device->devdata.device = hid_open_path(device->path, 0);
12.42 + if (!device->devdata.device) {
12.43 + SDL_SetError("Couldn't open HID device %s", device->path);
12.44 + device->driver = NULL;
12.45 + } else {
12.46 + device->driver->InitDriver(
12.47 + &device->devdata,
12.48 + device->vendor_id,
12.49 + device->product_id,
12.50 + &SDL_HIDAPI_numjoysticks
12.51 + );
12.52 + device->mutex = SDL_CreateMutex();
12.53 + }
12.54 +}
12.55 +
12.56 +static void
12.57 +HIDAPI_QuitDriver(SDL_HIDAPI_Device *device, SDL_bool send_event)
12.58 +{
12.59 + device->driver->QuitDriver(
12.60 + &device->devdata,
12.61 + send_event,
12.62 + &SDL_HIDAPI_numjoysticks
12.63 + );
12.64 + hid_close(device->devdata.device);
12.65 + SDL_DestroyMutex(device->mutex);
12.66 + device->driver = NULL;
12.67 +}
12.68
12.69 const char *
12.70 HIDAPI_XboxControllerName(Uint16 vendor_id, Uint16 product_id)
12.71 @@ -605,15 +630,17 @@
12.72 }
12.73
12.74 static SDL_HIDAPI_Device *
12.75 -HIDAPI_GetJoystickByIndex(int device_index)
12.76 +HIDAPI_GetDeviceByIndex(int device_index)
12.77 {
12.78 SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
12.79 + int joysticks;
12.80 while (device) {
12.81 if (device->driver) {
12.82 - if (device_index == 0) {
12.83 + joysticks = device->driver->NumJoysticks(&device->devdata);
12.84 + if (device_index < joysticks) {
12.85 break;
12.86 }
12.87 - --device_index;
12.88 + device_index -= joysticks;
12.89 }
12.90 device = device->next;
12.91 }
12.92 @@ -660,20 +687,12 @@
12.93 while (device) {
12.94 if (device->driver) {
12.95 if (!device->driver->enabled) {
12.96 - device->driver = NULL;
12.97 -
12.98 - --SDL_HIDAPI_numjoysticks;
12.99 -
12.100 - SDL_PrivateJoystickRemoved(device->instance_id);
12.101 + HIDAPI_QuitDriver(device, SDL_TRUE);
12.102 }
12.103 } else {
12.104 device->driver = HIDAPI_GetDeviceDriver(device);
12.105 if (device->driver) {
12.106 - device->instance_id = SDL_GetNextJoystickInstanceID();
12.107 -
12.108 - ++SDL_HIDAPI_numjoysticks;
12.109 -
12.110 - SDL_PrivateJoystickAdded(device->instance_id);
12.111 + HIDAPI_InitDriver(device);
12.112 }
12.113 }
12.114 device = device->next;
12.115 @@ -723,7 +742,6 @@
12.116 if (!device) {
12.117 return;
12.118 }
12.119 - device->instance_id = -1;
12.120 device->seen = SDL_TRUE;
12.121 device->vendor_id = info->vendor_id;
12.122 device->product_id = info->product_id;
12.123 @@ -818,12 +836,8 @@
12.124 }
12.125
12.126 if (device->driver) {
12.127 - /* It's a joystick! */
12.128 - device->instance_id = SDL_GetNextJoystickInstanceID();
12.129 -
12.130 - ++SDL_HIDAPI_numjoysticks;
12.131 -
12.132 - SDL_PrivateJoystickAdded(device->instance_id);
12.133 + /* It's a joystick device! */
12.134 + HIDAPI_InitDriver(device);
12.135 }
12.136 }
12.137
12.138 @@ -840,11 +854,8 @@
12.139 SDL_HIDAPI_devices = curr->next;
12.140 }
12.141
12.142 - if (device->driver && send_event) {
12.143 - /* Need to decrement the joystick count before we post the event */
12.144 - --SDL_HIDAPI_numjoysticks;
12.145 -
12.146 - SDL_PrivateJoystickRemoved(device->instance_id);
12.147 + if (device->driver) {
12.148 + HIDAPI_QuitDriver(device, send_event);
12.149 }
12.150
12.151 SDL_free(device->name);
12.152 @@ -931,7 +942,7 @@
12.153 static const char *
12.154 HIDAPI_JoystickGetDeviceName(int device_index)
12.155 {
12.156 - return HIDAPI_GetJoystickByIndex(device_index)->name;
12.157 + return HIDAPI_GetDeviceByIndex(device_index)->name;
12.158 }
12.159
12.160 static int
12.161 @@ -943,89 +954,61 @@
12.162 static SDL_JoystickGUID
12.163 HIDAPI_JoystickGetDeviceGUID(int device_index)
12.164 {
12.165 - return HIDAPI_GetJoystickByIndex(device_index)->guid;
12.166 + return HIDAPI_GetDeviceByIndex(device_index)->guid;
12.167 }
12.168
12.169 static SDL_JoystickID
12.170 HIDAPI_JoystickGetDeviceInstanceID(int device_index)
12.171 {
12.172 - return HIDAPI_GetJoystickByIndex(device_index)->instance_id;
12.173 + SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
12.174 + int joysticks;
12.175 + while (device) {
12.176 + if (device->driver) {
12.177 + joysticks = device->driver->NumJoysticks(&device->devdata);
12.178 + if (device_index < joysticks) {
12.179 + break;
12.180 + }
12.181 + device_index -= joysticks;
12.182 + }
12.183 + device = device->next;
12.184 + }
12.185 + return device->driver->InstanceIDForIndex(&device->devdata, device_index);
12.186 }
12.187
12.188 static int
12.189 HIDAPI_JoystickOpen(SDL_Joystick * joystick, int device_index)
12.190 {
12.191 - SDL_HIDAPI_Device *device = HIDAPI_GetJoystickByIndex(device_index);
12.192 - struct joystick_hwdata *hwdata;
12.193 -
12.194 - hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
12.195 - if (!hwdata) {
12.196 - return SDL_OutOfMemory();
12.197 - }
12.198 + SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index);
12.199
12.200 - hwdata->driver = device->driver;
12.201 - hwdata->dev = hid_open_path(device->path, 0);
12.202 - if (!hwdata->dev) {
12.203 - SDL_free(hwdata);
12.204 - return SDL_SetError("Couldn't open HID device %s", device->path);
12.205 - }
12.206 - hwdata->mutex = SDL_CreateMutex();
12.207 -
12.208 - if (!device->driver->Init(joystick, hwdata->dev, device->vendor_id, device->product_id, &hwdata->context)) {
12.209 - hid_close(hwdata->dev);
12.210 - SDL_free(hwdata);
12.211 + if (!device->driver->OpenJoystick(&device->devdata, joystick)) {
12.212 return -1;
12.213 }
12.214
12.215 - joystick->hwdata = hwdata;
12.216 + joystick->hwdata = (struct joystick_hwdata *)device;
12.217 return 0;
12.218 }
12.219
12.220 static int
12.221 HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
12.222 {
12.223 - struct joystick_hwdata *hwdata = joystick->hwdata;
12.224 - SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
12.225 + SDL_HIDAPI_Device *device = (SDL_HIDAPI_Device *)joystick->hwdata;
12.226 int result;
12.227
12.228 - SDL_LockMutex(hwdata->mutex);
12.229 - result = driver->Rumble(joystick, hwdata->dev, hwdata->context, low_frequency_rumble, high_frequency_rumble, duration_ms);
12.230 - SDL_UnlockMutex(hwdata->mutex);
12.231 + SDL_LockMutex(device->mutex);
12.232 + result = device->driver->Rumble(&device->devdata, joystick, low_frequency_rumble, high_frequency_rumble, duration_ms);
12.233 + SDL_UnlockMutex(device->mutex);
12.234 return result;
12.235 }
12.236
12.237 static void
12.238 HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
12.239 {
12.240 - struct joystick_hwdata *hwdata = joystick->hwdata;
12.241 - SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
12.242 - SDL_bool succeeded;
12.243 -
12.244 - SDL_LockMutex(hwdata->mutex);
12.245 - succeeded = driver->Update(joystick, hwdata->dev, hwdata->context);
12.246 - SDL_UnlockMutex(hwdata->mutex);
12.247 -
12.248 - if (!succeeded) {
12.249 - SDL_HIDAPI_Device *device;
12.250 - for (device = SDL_HIDAPI_devices; device; device = device->next) {
12.251 - if (device->instance_id == joystick->instance_id) {
12.252 - HIDAPI_DelDevice(device, SDL_TRUE);
12.253 - break;
12.254 - }
12.255 - }
12.256 - }
12.257 + /* No-op, all updates are done in SDL_HIDAPI_UpdateDevices */
12.258 }
12.259
12.260 static void
12.261 HIDAPI_JoystickClose(SDL_Joystick * joystick)
12.262 {
12.263 - struct joystick_hwdata *hwdata = joystick->hwdata;
12.264 - SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
12.265 - driver->Quit(joystick, hwdata->dev, hwdata->context);
12.266 -
12.267 - hid_close(hwdata->dev);
12.268 - SDL_DestroyMutex(hwdata->mutex);
12.269 - SDL_free(hwdata);
12.270 joystick->hwdata = NULL;
12.271 }
12.272
12.273 @@ -1050,6 +1033,30 @@
12.274 hid_exit();
12.275 }
12.276
12.277 +void
12.278 +SDL_HIDAPI_UpdateDevices(void)
12.279 +{
12.280 + SDL_HIDAPI_Device *next, *device = SDL_HIDAPI_devices;
12.281 + SDL_bool succeeded;
12.282 +
12.283 + while (device) {
12.284 + if (device->driver) {
12.285 + SDL_LockMutex(device->mutex);
12.286 + succeeded = device->driver->UpdateDriver(&device->devdata, &SDL_HIDAPI_numjoysticks);
12.287 + SDL_UnlockMutex(device->mutex);
12.288 + if (!succeeded) {
12.289 + next = device->next;
12.290 + HIDAPI_DelDevice(device, SDL_TRUE);
12.291 + device = next;
12.292 + } else {
12.293 + device = device->next;
12.294 + }
12.295 + } else {
12.296 + device = device->next;
12.297 + }
12.298 + }
12.299 +}
12.300 +
12.301 SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
12.302 {
12.303 HIDAPI_JoystickInit,
13.1 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h Sat Mar 16 17:47:59 2019 -0700
13.2 +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h Tue Mar 12 20:27:54 2019 -0400
13.3 @@ -30,6 +30,7 @@
13.4 #define SDL_JOYSTICK_HIDAPI_SWITCH
13.5 #define SDL_JOYSTICK_HIDAPI_XBOX360
13.6 #define SDL_JOYSTICK_HIDAPI_XBOXONE
13.7 +#define SDL_JOYSTICK_HIDAPI_GAMECUBE
13.8
13.9 #ifdef __WINDOWS__
13.10 /* On Windows, Xbox One controllers are handled by the Xbox 360 driver */
13.11 @@ -43,16 +44,36 @@
13.12 #undef SDL_JOYSTICK_HIDAPI_XBOXONE
13.13 #endif
13.14
13.15 +typedef struct _SDL_HIDAPI_DriverData
13.16 +{
13.17 + hid_device *device;
13.18 + void *context;
13.19 +} SDL_HIDAPI_DriverData;
13.20 +
13.21 typedef struct _SDL_HIDAPI_DeviceDriver
13.22 {
13.23 const char *hint;
13.24 SDL_bool enabled;
13.25 SDL_bool (*IsSupportedDevice)(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number);
13.26 const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id);
13.27 - SDL_bool (*Init)(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context);
13.28 - int (*Rumble)(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
13.29 - SDL_bool (*Update)(SDL_Joystick *joystick, hid_device *dev, void *context);
13.30 - void (*Quit)(SDL_Joystick *joystick, hid_device *dev, void *context);
13.31 +
13.32 + SDL_bool (*InitDriver)(SDL_HIDAPI_DriverData *context,
13.33 + Uint16 vendor_id, Uint16 product_id, int *num_joysticks);
13.34 + void (*QuitDriver)(SDL_HIDAPI_DriverData *context,
13.35 + SDL_bool send_event,
13.36 + int *num_joysticks);
13.37 + SDL_bool (*UpdateDriver)(SDL_HIDAPI_DriverData *context,
13.38 + int *num_joysticks);
13.39 + int (*NumJoysticks)(SDL_HIDAPI_DriverData *context);
13.40 + SDL_JoystickID (*InstanceIDForIndex)(SDL_HIDAPI_DriverData *context,
13.41 + int index);
13.42 + SDL_bool (*OpenJoystick)(SDL_HIDAPI_DriverData *context,
13.43 + SDL_Joystick *joystick);
13.44 + int (*Rumble)(SDL_HIDAPI_DriverData *context,
13.45 + SDL_Joystick *joystick,
13.46 + Uint16 low_frequency_rumble,
13.47 + Uint16 high_frequency_rumble,
13.48 + Uint32 duration_ms);
13.49
13.50 } SDL_HIDAPI_DeviceDriver;
13.51
13.52 @@ -62,6 +83,7 @@
13.53 extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch;
13.54 extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360;
13.55 extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne;
13.56 +extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube;
13.57
13.58 /* Return true if a HID device is present and supported as a joystick */
13.59 extern SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version);