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.
parent
938a5508d1
commit
c528615626
|
@ -555,6 +555,17 @@ extern "C" {
|
|||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - HIDAPI driver is not used
|
||||
* "1" - HIDAPI driver is used
|
||||
*
|
||||
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE"
|
||||
|
||||
/**
|
||||
* \brief A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
|
||||
*
|
||||
|
|
|
@ -564,6 +564,7 @@ static const char *s_ControllerMappings [] =
|
|||
"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,",
|
||||
"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,",
|
||||
"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,",
|
||||
"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,",
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
"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,",
|
||||
|
|
|
@ -1033,6 +1033,11 @@ SDL_JoystickUpdate(void)
|
|||
/* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
|
||||
SDL_UnlockJoysticks();
|
||||
|
||||
/* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
SDL_HIDAPI_UpdateDevices();
|
||||
#endif /* SDL_JOYSTICK_HIDAPI */
|
||||
|
||||
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
|
||||
if (joystick->attached) {
|
||||
joystick->driver->Update(joystick);
|
||||
|
@ -1187,6 +1192,12 @@ SDL_IsJoystickXboxOne(Uint16 vendor, Uint16 product)
|
|||
return (GuessControllerType(vendor, product) == k_eControllerType_XBoxOneController);
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IsJoystickGameCube(Uint16 vendor, Uint16 product)
|
||||
{
|
||||
return (GuessControllerType(vendor, product) == k_eControllerType_GameCube);
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IsJoystickXInput(SDL_JoystickGUID guid)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,9 @@ extern SDL_bool SDL_IsJoystickXbox360(Uint16 vendor_id, Uint16 product_id);
|
|||
/* Function to return whether a joystick is an Xbox One controller */
|
||||
extern SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id);
|
||||
|
||||
/* Function to return whether a joystick is a GameCube controller */
|
||||
extern SDL_bool SDL_IsJoystickGameCube(Uint16 vendor_id, Uint16 product_id);
|
||||
|
||||
/* Function to return whether a joystick guid comes from the XInput driver */
|
||||
extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid);
|
||||
|
||||
|
|
|
@ -152,6 +152,9 @@ extern SDL_JoystickDriver SDL_IOS_JoystickDriver;
|
|||
extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
|
||||
extern SDL_JoystickDriver SDL_WINDOWS_JoystickDriver;
|
||||
|
||||
/* Special function to update HIDAPI devices */
|
||||
extern void SDL_HIDAPI_UpdateDevices(void);
|
||||
|
||||
#endif /* SDL_sysjoystick_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -57,6 +57,7 @@ typedef enum
|
|||
k_eControllerType_SwitchJoyConPair = 41,
|
||||
k_eControllerType_SwitchInputOnlyController = 42,
|
||||
k_eControllerType_MobileTouch = 43,
|
||||
k_eControllerType_GameCube = 44,
|
||||
k_eControllerType_LastController, // Don't add game controllers below this enumeration - this enumeration can change value
|
||||
|
||||
// Keyboards and Mice
|
||||
|
@ -387,6 +388,8 @@ static const ControllerDescription_t arrControllers[] = {
|
|||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa711 ), k_eControllerType_SwitchInputOnlyController }, // PowerA Wired Controller Plus
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0092 ), k_eControllerType_SwitchInputOnlyController }, // HORI Pokken Tournament DX Pro Pad
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x057e, 0x0337 ), k_eControllerType_GameCube }, // Nintendo Wii U/Switch GameCube USB Adapter
|
||||
|
||||
|
||||
// Valve products - don't add to public list
|
||||
{ MAKE_CONTROLLER_ID( 0x0000, 0x11fb ), k_eControllerType_MobileTouch }, // Streaming mobile touch virtual controls
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_haptic.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_gamecontroller.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "SDL_hidapijoystick_c.h"
|
||||
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
|
||||
|
||||
typedef struct {
|
||||
SDL_JoystickID joysticks[4];
|
||||
Uint8 rumble[5];
|
||||
Uint32 rumbleExpiration[4];
|
||||
/* Without this variable, hid_write starts to lag a TON */
|
||||
Uint8 rumbleUpdate;
|
||||
} SDL_DriverGameCube_Context;
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverGameCube_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number)
|
||||
{
|
||||
return SDL_IsJoystickGameCube(vendor_id, product_id);
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverGameCube_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
/* Give a user friendly name for this controller */
|
||||
if (SDL_IsJoystickGameCube(vendor_id, product_id)) {
|
||||
return "Nintendo GameCube Controller";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverGameCube_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx;
|
||||
Uint8 packet[37];
|
||||
Uint8 *curSlot;
|
||||
Uint8 i;
|
||||
int size;
|
||||
Uint8 initMagic = 0x13;
|
||||
Uint8 rumbleMagic = 0x11;
|
||||
|
||||
ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
SDL_OutOfMemory();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
ctx->joysticks[0] = -1;
|
||||
ctx->joysticks[1] = -1;
|
||||
ctx->joysticks[2] = -1;
|
||||
ctx->joysticks[3] = -1;
|
||||
ctx->rumble[0] = rumbleMagic;
|
||||
|
||||
context->context = ctx;
|
||||
|
||||
/* This is all that's needed to initialize the device. Really! */
|
||||
if (hid_write(context->device, &initMagic, sizeof(initMagic)) <= 0) {
|
||||
SDL_SetError("Couldn't initialize WUP-028");
|
||||
SDL_free(ctx);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Add all the applicable joysticks */
|
||||
while ((size = hid_read_timeout(context->device, packet, sizeof(packet), 0)) > 0) {
|
||||
if (size < 37 || packet[0] != 0x21) {
|
||||
continue; /* Nothing to do yet...? */
|
||||
}
|
||||
|
||||
/* Go through all 4 slots */
|
||||
curSlot = packet + 1;
|
||||
for (i = 0; i < 4; i += 1, curSlot += 9) {
|
||||
if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
|
||||
if (ctx->joysticks[i] == -1) {
|
||||
ctx->joysticks[i] = SDL_GetNextJoystickInstanceID();
|
||||
|
||||
*num_joysticks += 1;
|
||||
|
||||
SDL_PrivateJoystickAdded(ctx->joysticks[i]);
|
||||
}
|
||||
} else {
|
||||
if (ctx->joysticks[i] != -1) {
|
||||
SDL_PrivateJoystickRemoved(ctx->joysticks[i]);
|
||||
|
||||
*num_joysticks -= 1;
|
||||
|
||||
ctx->joysticks[i] = -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverGameCube_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
|
||||
Uint8 i;
|
||||
|
||||
/* Stop all rumble activity */
|
||||
for (i = 1; i < 5; i += 1) {
|
||||
ctx->rumble[i] = 0;
|
||||
}
|
||||
hid_write(context->device, ctx->rumble, sizeof(ctx->rumble));
|
||||
|
||||
/* Remove all joysticks! */
|
||||
for (i = 0; i < 4; i += 1) {
|
||||
if (ctx->joysticks[i] != -1) {
|
||||
*num_joysticks -= 1;
|
||||
if (send_event) {
|
||||
SDL_PrivateJoystickRemoved(ctx->joysticks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(context->context);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverGameCube_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
|
||||
SDL_Joystick *joystick;
|
||||
Uint8 packet[37];
|
||||
Uint8 *curSlot;
|
||||
Uint32 now;
|
||||
Uint8 i;
|
||||
int size;
|
||||
|
||||
/* Read input packet */
|
||||
while ((size = hid_read_timeout(context->device, packet, sizeof(packet), 0)) > 0) {
|
||||
if (size < 37 || packet[0] != 0x21) {
|
||||
continue; /* Nothing to do right now...? */
|
||||
}
|
||||
|
||||
/* Go through all 4 slots */
|
||||
curSlot = packet + 1;
|
||||
for (i = 0; i < 4; i += 1, curSlot += 9) {
|
||||
if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
|
||||
if (ctx->joysticks[i] == -1) {
|
||||
ctx->joysticks[i] = SDL_GetNextJoystickInstanceID();
|
||||
|
||||
*num_joysticks += 1;
|
||||
|
||||
SDL_PrivateJoystickAdded(ctx->joysticks[i]);
|
||||
}
|
||||
joystick = SDL_JoystickFromInstanceID(ctx->joysticks[i]);
|
||||
|
||||
/* Hasn't been opened yet, skip */
|
||||
if (joystick == NULL) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (ctx->joysticks[i] != -1) {
|
||||
SDL_PrivateJoystickRemoved(ctx->joysticks[i]);
|
||||
|
||||
*num_joysticks -= 1;
|
||||
|
||||
ctx->joysticks[i] = -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#define READ_BUTTON(off, flag, button) \
|
||||
SDL_PrivateJoystickButton( \
|
||||
joystick, \
|
||||
button, \
|
||||
(curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED \
|
||||
);
|
||||
READ_BUTTON(1, 0x01, 0) /* A */
|
||||
READ_BUTTON(1, 0x02, 1) /* B */
|
||||
READ_BUTTON(1, 0x04, 2) /* X */
|
||||
READ_BUTTON(1, 0x08, 3) /* Y */
|
||||
READ_BUTTON(1, 0x10, 4) /* DPAD_LEFT */
|
||||
READ_BUTTON(1, 0x20, 5) /* DPAD_RIGHT */
|
||||
READ_BUTTON(1, 0x40, 6) /* DPAD_DOWN */
|
||||
READ_BUTTON(1, 0x80, 7) /* DPAD_UP */
|
||||
READ_BUTTON(2, 0x01, 8) /* START */
|
||||
READ_BUTTON(2, 0x02, 9) /* RIGHTSHOULDER */
|
||||
/* [2] 0x04 - R, [2] 0x08 - L */
|
||||
#undef READ_BUTTON
|
||||
|
||||
/* Axis math taken from SDL_xinputjoystick.c */
|
||||
#define READ_AXIS(off, axis) \
|
||||
SDL_PrivateJoystickAxis( \
|
||||
joystick, \
|
||||
axis, \
|
||||
(Sint16)(((int)curSlot[off] * 257) - 32768) \
|
||||
);
|
||||
READ_AXIS(3, 0) /* LEFTX */
|
||||
READ_AXIS(4, 1) /* LEFTY */
|
||||
READ_AXIS(5, 2) /* RIGHTX */
|
||||
READ_AXIS(6, 3) /* RIGHTY */
|
||||
READ_AXIS(7, 4) /* TRIGGERLEFT */
|
||||
READ_AXIS(8, 5) /* TRIGGERRIGHT */
|
||||
#undef READ_AXIS
|
||||
}
|
||||
}
|
||||
|
||||
/* Write rumble packet */
|
||||
now = SDL_GetTicks();
|
||||
for (i = 0; i < 4; i += 1) {
|
||||
if (ctx->rumbleExpiration[i] > 0) {
|
||||
if (SDL_TICKS_PASSED(now, ctx->rumbleExpiration[i])) {
|
||||
ctx->rumble[i + 1] = 0;
|
||||
ctx->rumbleExpiration[i] = 0;
|
||||
ctx->rumbleUpdate = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ctx->rumbleUpdate) {
|
||||
hid_write(context->device, ctx->rumble, sizeof(ctx->rumble));
|
||||
ctx->rumbleUpdate = 0;
|
||||
}
|
||||
|
||||
/* If we got here, nothing bad happened! */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverGameCube_NumJoysticks(SDL_HIDAPI_DriverData *context)
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
|
||||
int i, joysticks = 0;
|
||||
for (i = 0; i < 4; i += 1) {
|
||||
if (ctx->joysticks[i] != -1) {
|
||||
joysticks += 1;
|
||||
}
|
||||
}
|
||||
return joysticks;
|
||||
}
|
||||
|
||||
static SDL_JoystickID
|
||||
HIDAPI_DriverGameCube_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
|
||||
Uint8 i;
|
||||
for (i = 0; i < 4; i += 1) {
|
||||
if (ctx->joysticks[i] != -1) {
|
||||
if (index == 0) {
|
||||
return ctx->joysticks[i];
|
||||
}
|
||||
index -= 1;
|
||||
}
|
||||
}
|
||||
return -1; /* Should never get here! */
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
|
||||
SDL_JoystickID instance = SDL_JoystickInstanceID(joystick);
|
||||
Uint8 i;
|
||||
for (i = 0; i < 4; i += 1) {
|
||||
if (instance == ctx->joysticks[i]) {
|
||||
joystick->nbuttons = 10;
|
||||
joystick->naxes = 6;
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE; /* Should never get here! */
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverGameCube_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
{
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)context->context;
|
||||
SDL_JoystickID instance = SDL_JoystickInstanceID(joystick);
|
||||
Uint8 i, val;
|
||||
for (i = 0; i < 4; i += 1) {
|
||||
if (instance == ctx->joysticks[i]) {
|
||||
val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
|
||||
if (val != ctx->rumble[i + 1]) {
|
||||
ctx->rumble[i + 1] = val;
|
||||
ctx->rumbleUpdate = 1;
|
||||
}
|
||||
if (val && duration_ms < SDL_HAPTIC_INFINITY) {
|
||||
ctx->rumbleExpiration[i] = SDL_GetTicks() + duration_ms;
|
||||
} else {
|
||||
ctx->rumbleExpiration[i] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
|
||||
{
|
||||
SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
|
||||
SDL_TRUE,
|
||||
HIDAPI_DriverGameCube_IsSupportedDevice,
|
||||
HIDAPI_DriverGameCube_GetDeviceName,
|
||||
HIDAPI_DriverGameCube_InitDriver,
|
||||
HIDAPI_DriverGameCube_QuitDriver,
|
||||
HIDAPI_DriverGameCube_UpdateDriver,
|
||||
HIDAPI_DriverGameCube_NumJoysticks,
|
||||
HIDAPI_DriverGameCube_InstanceIDForIndex,
|
||||
HIDAPI_DriverGameCube_OpenJoystick,
|
||||
HIDAPI_DriverGameCube_Rumble
|
||||
};
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI_GAMECUBE */
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI */
|
|
@ -108,6 +108,7 @@ typedef struct
|
|||
} DS4EffectsState_t;
|
||||
|
||||
typedef struct {
|
||||
SDL_JoystickID joystickID;
|
||||
SDL_bool is_dongle;
|
||||
SDL_bool is_bluetooth;
|
||||
SDL_bool audio_supported;
|
||||
|
@ -272,10 +273,8 @@ static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static int HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverPS4_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
|
||||
HIDAPI_DriverPS4_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx;
|
||||
|
||||
|
@ -284,14 +283,14 @@ HIDAPI_DriverPS4_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id,
|
|||
SDL_OutOfMemory();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
*context = ctx;
|
||||
context->context = ctx;
|
||||
|
||||
/* Check for type of connection */
|
||||
ctx->is_dongle = (vendor_id == SONY_USB_VID && product_id == SONY_DS4_DONGLE_PID);
|
||||
if (ctx->is_dongle) {
|
||||
ctx->is_bluetooth = SDL_FALSE;
|
||||
} else if (vendor_id == SONY_USB_VID) {
|
||||
ctx->is_bluetooth = !CheckUSBConnected(dev);
|
||||
ctx->is_bluetooth = !CheckUSBConnected(context->device);
|
||||
} else {
|
||||
/* Third party controllers appear to all be wired */
|
||||
ctx->is_bluetooth = SDL_FALSE;
|
||||
|
@ -314,8 +313,45 @@ HIDAPI_DriverPS4_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id,
|
|||
}
|
||||
}
|
||||
|
||||
ctx->joystickID = SDL_GetNextJoystickInstanceID();
|
||||
*num_joysticks += 1;
|
||||
SDL_PrivateJoystickAdded(ctx->joystickID);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverPS4_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
|
||||
|
||||
*num_joysticks -= 1;
|
||||
if (send_event) {
|
||||
SDL_PrivateJoystickRemoved(ctx->joystickID);
|
||||
}
|
||||
SDL_free(context->context);
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverPS4_NumJoysticks(SDL_HIDAPI_DriverData *context)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SDL_JoystickID
|
||||
HIDAPI_DriverPS4_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
|
||||
return ctx->joystickID;
|
||||
}
|
||||
|
||||
static int HIDAPI_DriverPS4_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
|
||||
{
|
||||
/* Initialize LED and effect state */
|
||||
HIDAPI_DriverPS4_Rumble(joystick, dev, ctx, 0, 0, 0);
|
||||
HIDAPI_DriverPS4_Rumble(context, joystick, 0, 0, 0);
|
||||
|
||||
/* Initialize the joystick capabilities */
|
||||
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
|
||||
|
@ -326,9 +362,9 @@ HIDAPI_DriverPS4_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id,
|
|||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
HIDAPI_DriverPS4_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context;
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
|
||||
DS4EffectsState_t *effects;
|
||||
Uint8 data[78];
|
||||
int report_size, offset;
|
||||
|
@ -386,7 +422,7 @@ HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context,
|
|||
SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
|
||||
}
|
||||
|
||||
if (hid_write(dev, data, report_size) != report_size) {
|
||||
if (hid_write(context->device, data, report_size) != report_size) {
|
||||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
|
||||
|
@ -508,20 +544,25 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverPS4_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
HIDAPI_DriverPS4_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context;
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context->context;
|
||||
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
int size;
|
||||
|
||||
while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
|
||||
if (joystick == NULL) {
|
||||
return SDL_TRUE; /* Nothing to do right now! */
|
||||
}
|
||||
|
||||
while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
|
||||
switch (data[0]) {
|
||||
case k_EPS4ReportIdUsbState:
|
||||
HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[1]);
|
||||
HIDAPI_DriverPS4_HandleStatePacket(joystick, context->device, ctx, (PS4StatePacket_t *)&data[1]);
|
||||
break;
|
||||
case k_EPS4ReportIdBluetoothState:
|
||||
/* Bluetooth state packets have two additional bytes at the beginning */
|
||||
HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[3]);
|
||||
HIDAPI_DriverPS4_HandleStatePacket(joystick, context->device, ctx, (PS4StatePacket_t *)&data[3]);
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
|
@ -534,29 +575,26 @@ HIDAPI_DriverPS4_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
|
|||
if (ctx->rumble_expiration) {
|
||||
Uint32 now = SDL_GetTicks();
|
||||
if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
|
||||
HIDAPI_DriverPS4_Rumble(joystick, dev, context, 0, 0, 0);
|
||||
HIDAPI_DriverPS4_Rumble(context, joystick, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return (size >= 0);
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverPS4_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
{
|
||||
SDL_free(context);
|
||||
}
|
||||
|
||||
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
|
||||
{
|
||||
SDL_HINT_JOYSTICK_HIDAPI_PS4,
|
||||
SDL_TRUE,
|
||||
HIDAPI_DriverPS4_IsSupportedDevice,
|
||||
HIDAPI_DriverPS4_GetDeviceName,
|
||||
HIDAPI_DriverPS4_Init,
|
||||
HIDAPI_DriverPS4_Rumble,
|
||||
HIDAPI_DriverPS4_Update,
|
||||
HIDAPI_DriverPS4_Quit
|
||||
HIDAPI_DriverPS4_InitDriver,
|
||||
HIDAPI_DriverPS4_QuitDriver,
|
||||
HIDAPI_DriverPS4_UpdateDriver,
|
||||
HIDAPI_DriverPS4_NumJoysticks,
|
||||
HIDAPI_DriverPS4_InstanceIDForIndex,
|
||||
HIDAPI_DriverPS4_OpenJoystick,
|
||||
HIDAPI_DriverPS4_Rumble
|
||||
};
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI_PS4 */
|
||||
|
|
|
@ -183,6 +183,7 @@ typedef struct
|
|||
#pragma pack()
|
||||
|
||||
typedef struct {
|
||||
SDL_JoystickID joystickID;
|
||||
hid_device *dev;
|
||||
SDL_bool m_bIsUsingBluetooth;
|
||||
Uint8 m_nCommandNumber;
|
||||
|
@ -570,7 +571,7 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
|
||||
HIDAPI_DriverSwitch_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx;
|
||||
Uint8 input_mode;
|
||||
|
@ -580,9 +581,9 @@ HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_
|
|||
SDL_OutOfMemory();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
ctx->dev = dev;
|
||||
ctx->dev = context->device;
|
||||
|
||||
*context = ctx;
|
||||
context->context = ctx;
|
||||
|
||||
/* Initialize rumble data */
|
||||
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
|
||||
|
@ -627,6 +628,18 @@ HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_
|
|||
}
|
||||
}
|
||||
|
||||
ctx->joystickID = SDL_GetNextJoystickInstanceID();
|
||||
*num_joysticks += 1;
|
||||
SDL_PrivateJoystickAdded(ctx->joystickID);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
|
||||
|
||||
/* Set the LED state */
|
||||
SetHomeLED(ctx, 100);
|
||||
SetSlotLED(ctx, (joystick->instance_id % 4));
|
||||
|
@ -640,9 +653,9 @@ HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_
|
|||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverSwitch_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
HIDAPI_DriverSwitch_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
|
||||
|
||||
/* Experimentally determined rumble values. These will only matter on some controllers as tested ones
|
||||
* seem to disregard these and just use any non-zero rumble values as a binary flag for constant rumble
|
||||
|
@ -847,11 +860,16 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverSwitch_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
HIDAPI_DriverSwitch_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
|
||||
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
|
||||
int size;
|
||||
|
||||
if (joystick == NULL) {
|
||||
return SDL_TRUE; /* Nothing to do right now! */
|
||||
}
|
||||
|
||||
while ((size = ReadInput(ctx)) > 0) {
|
||||
switch (ctx->m_rgucReadBuffer[0]) {
|
||||
case k_eSwitchInputReportIDs_SimpleControllerState:
|
||||
|
@ -868,7 +886,7 @@ HIDAPI_DriverSwitch_Update(SDL_Joystick *joystick, hid_device *dev, void *contex
|
|||
if (ctx->m_nRumbleExpiration) {
|
||||
Uint32 now = SDL_GetTicks();
|
||||
if (SDL_TICKS_PASSED(now, ctx->m_nRumbleExpiration)) {
|
||||
HIDAPI_DriverSwitch_Rumble(joystick, dev, context, 0, 0, 0);
|
||||
HIDAPI_DriverSwitch_Rumble(context, joystick, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -876,14 +894,31 @@ HIDAPI_DriverSwitch_Update(SDL_Joystick *joystick, hid_device *dev, void *contex
|
|||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverSwitch_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
HIDAPI_DriverSwitch_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
|
||||
|
||||
/* Restore simple input mode for other applications */
|
||||
SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
|
||||
|
||||
SDL_free(context);
|
||||
*num_joysticks -= 1;
|
||||
if (send_event) {
|
||||
SDL_PrivateJoystickRemoved(ctx->joystickID);
|
||||
}
|
||||
SDL_free(context->context);
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverSwitch_NumJoysticks(SDL_HIDAPI_DriverData *context)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SDL_JoystickID
|
||||
HIDAPI_DriverSwitch_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context->context;
|
||||
return ctx->joystickID;
|
||||
}
|
||||
|
||||
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
|
||||
|
@ -892,10 +927,13 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
|
|||
SDL_TRUE,
|
||||
HIDAPI_DriverSwitch_IsSupportedDevice,
|
||||
HIDAPI_DriverSwitch_GetDeviceName,
|
||||
HIDAPI_DriverSwitch_Init,
|
||||
HIDAPI_DriverSwitch_Rumble,
|
||||
HIDAPI_DriverSwitch_Update,
|
||||
HIDAPI_DriverSwitch_Quit
|
||||
HIDAPI_DriverSwitch_InitDriver,
|
||||
HIDAPI_DriverSwitch_QuitDriver,
|
||||
HIDAPI_DriverSwitch_UpdateDriver,
|
||||
HIDAPI_DriverSwitch_NumJoysticks,
|
||||
HIDAPI_DriverSwitch_InstanceIDForIndex,
|
||||
HIDAPI_DriverSwitch_OpenJoystick,
|
||||
HIDAPI_DriverSwitch_Rumble
|
||||
};
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI_SWITCH */
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
|
||||
typedef struct {
|
||||
SDL_JoystickID joystickID;
|
||||
Uint8 last_state[USB_PACKET_LENGTH];
|
||||
Uint32 rumble_expiration;
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
|
||||
|
@ -277,7 +278,7 @@ static SDL_bool SetSlotLED(hid_device *dev, Uint8 slot)
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXbox360_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
|
||||
HIDAPI_DriverXbox360_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverXbox360_Context *ctx;
|
||||
|
||||
|
@ -296,10 +297,20 @@ HIDAPI_DriverXbox360_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor
|
|||
#ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
|
||||
HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
|
||||
#endif
|
||||
*context = ctx;
|
||||
context->context = ctx;
|
||||
|
||||
ctx->joystickID = SDL_GetNextJoystickInstanceID();
|
||||
*num_joysticks += 1;
|
||||
SDL_PrivateJoystickAdded(ctx->joystickID);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
|
||||
{
|
||||
/* Set the controller LED */
|
||||
SetSlotLED(dev, (joystick->instance_id % 4));
|
||||
SetSlotLED(context->device, (joystick->instance_id % 4));
|
||||
|
||||
/* Initialize the joystick capabilities */
|
||||
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
|
||||
|
@ -310,9 +321,22 @@ HIDAPI_DriverXbox360_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor
|
|||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverXbox360_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
HIDAPI_DriverXbox360_NumJoysticks(SDL_HIDAPI_DriverData *context)
|
||||
{
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SDL_JoystickID
|
||||
HIDAPI_DriverXbox360_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
|
||||
{
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
|
||||
return ctx->joystickID;
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverXbox360_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
{
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
|
||||
|
||||
#ifdef __WIN32__
|
||||
SDL_bool rumbled = SDL_FALSE;
|
||||
|
@ -365,7 +389,7 @@ HIDAPI_DriverXbox360_Rumble(SDL_Joystick *joystick, hid_device *dev, void *conte
|
|||
rumble_packet[4] = (high_frequency_rumble >> 8);
|
||||
#endif
|
||||
|
||||
if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||
if (hid_write(context->device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
#endif /* __WIN32__ */
|
||||
|
@ -705,26 +729,31 @@ HIDAPI_DriverXboxOneS_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev,
|
|||
#endif /* __MACOSX__ */
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
HIDAPI_DriverXbox360_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
|
||||
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
int size;
|
||||
|
||||
while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
|
||||
if (joystick == NULL) {
|
||||
return SDL_TRUE; /* Nothing to do right now! */
|
||||
}
|
||||
|
||||
while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
|
||||
#ifdef __WIN32__
|
||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, dev, ctx, data, size);
|
||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, context->device, ctx, data, size);
|
||||
#else
|
||||
switch (data[0]) {
|
||||
case 0x00:
|
||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, dev, ctx, data, size);
|
||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, context->device, ctx, data, size);
|
||||
break;
|
||||
#ifdef __MACOSX__
|
||||
case 0x01:
|
||||
HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, dev, ctx, data, size);
|
||||
HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, context->device, ctx, data, size);
|
||||
break;
|
||||
case 0x02:
|
||||
HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, dev, ctx, data, size);
|
||||
HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, context->device, ctx, data, size);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -742,7 +771,7 @@ HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *conte
|
|||
if (ctx->rumble_expiration) {
|
||||
Uint32 now = SDL_GetTicks();
|
||||
if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
|
||||
HIDAPI_DriverXbox360_Rumble(joystick, dev, context, 0, 0, 0);
|
||||
HIDAPI_DriverXbox360_Rumble(context, joystick, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,11 +779,9 @@ HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *conte
|
|||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverXbox360_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
HIDAPI_DriverXbox360_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
|
||||
{
|
||||
#if defined(SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT) || defined(SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT)
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
|
||||
#endif
|
||||
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
|
||||
if (ctx->xinput_enabled) {
|
||||
|
@ -765,7 +792,11 @@ HIDAPI_DriverXbox360_Quit(SDL_Joystick *joystick, hid_device *dev, void *context
|
|||
#ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
|
||||
HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
|
||||
#endif
|
||||
SDL_free(context);
|
||||
*num_joysticks -= 1;
|
||||
if (send_event) {
|
||||
SDL_PrivateJoystickRemoved(ctx->joystickID);
|
||||
}
|
||||
SDL_free(context->context);
|
||||
}
|
||||
|
||||
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
|
||||
|
@ -774,10 +805,13 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
|
|||
SDL_TRUE,
|
||||
HIDAPI_DriverXbox360_IsSupportedDevice,
|
||||
HIDAPI_DriverXbox360_GetDeviceName,
|
||||
HIDAPI_DriverXbox360_Init,
|
||||
HIDAPI_DriverXbox360_Rumble,
|
||||
HIDAPI_DriverXbox360_Update,
|
||||
HIDAPI_DriverXbox360_Quit
|
||||
HIDAPI_DriverXbox360_InitDriver,
|
||||
HIDAPI_DriverXbox360_QuitDriver,
|
||||
HIDAPI_DriverXbox360_UpdateDriver,
|
||||
HIDAPI_DriverXbox360_NumJoysticks,
|
||||
HIDAPI_DriverXbox360_InstanceIDForIndex,
|
||||
HIDAPI_DriverXbox360_OpenJoystick,
|
||||
HIDAPI_DriverXbox360_Rumble
|
||||
};
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI_XBOX360 */
|
||||
|
|
|
@ -124,6 +124,7 @@ static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
SDL_JoystickID joystickID;
|
||||
Uint8 sequence;
|
||||
Uint8 last_state[USB_PACKET_LENGTH];
|
||||
Uint32 rumble_expiration;
|
||||
|
@ -143,7 +144,7 @@ HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
|
||||
HIDAPI_DriverXboxOne_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx;
|
||||
int i;
|
||||
|
@ -154,7 +155,7 @@ HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor
|
|||
SDL_OutOfMemory();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
*context = ctx;
|
||||
context->context = ctx;
|
||||
|
||||
/* Send the controller init data */
|
||||
for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
|
||||
|
@ -162,7 +163,7 @@ HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor
|
|||
if (!packet->vendor_id || (vendor_id == packet->vendor_id && product_id == packet->product_id)) {
|
||||
SDL_memcpy(init_packet, packet->data, packet->size);
|
||||
init_packet[2] = ctx->sequence++;
|
||||
if (hid_write(dev, init_packet, packet->size) != packet->size) {
|
||||
if (hid_write(context->device, init_packet, packet->size) != packet->size) {
|
||||
SDL_SetError("Couldn't write Xbox One initialization packet");
|
||||
SDL_free(ctx);
|
||||
return SDL_FALSE;
|
||||
|
@ -170,6 +171,16 @@ HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor
|
|||
}
|
||||
}
|
||||
|
||||
ctx->joystickID = SDL_GetNextJoystickInstanceID();
|
||||
*num_joysticks += 1;
|
||||
SDL_PrivateJoystickAdded(ctx->joystickID);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
|
||||
{
|
||||
/* Initialize the joystick capabilities */
|
||||
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
|
||||
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
||||
|
@ -178,10 +189,35 @@ HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverXboxOne_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
static void
|
||||
HIDAPI_DriverXboxOne_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
|
||||
|
||||
*num_joysticks -= 1;
|
||||
if (send_event) {
|
||||
SDL_PrivateJoystickRemoved(ctx->joystickID);
|
||||
}
|
||||
SDL_free(context->context);
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverXboxOne_NumJoysticks(SDL_HIDAPI_DriverData *context)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SDL_JoystickID
|
||||
HIDAPI_DriverXboxOne_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
|
||||
return ctx->joystickID;
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_DriverXboxOne_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
|
||||
Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
|
||||
|
||||
/* The Rock Candy Xbox One Controller limits the range of
|
||||
|
@ -194,7 +230,7 @@ HIDAPI_DriverXboxOne_Rumble(SDL_Joystick *joystick, hid_device *dev, void *conte
|
|||
rumble_packet[8] = (low_frequency_rumble >> 9);
|
||||
rumble_packet[9] = (high_frequency_rumble >> 9);
|
||||
|
||||
if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||
if (hid_write(context->device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
|
||||
|
@ -267,19 +303,24 @@ HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, S
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
HIDAPI_DriverXboxOne_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context->context;
|
||||
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
int size;
|
||||
|
||||
while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
|
||||
if (joystick == NULL) {
|
||||
return SDL_TRUE; /* Nothing to do right now! */
|
||||
}
|
||||
|
||||
while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
|
||||
switch (data[0]) {
|
||||
case 0x20:
|
||||
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, dev, ctx, data, size);
|
||||
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, context->device, ctx, data, size);
|
||||
break;
|
||||
case 0x07:
|
||||
HIDAPI_DriverXboxOne_HandleModePacket(joystick, dev, ctx, data, size);
|
||||
HIDAPI_DriverXboxOne_HandleModePacket(joystick, context->device, ctx, data, size);
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
|
@ -292,29 +333,26 @@ HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev, void *conte
|
|||
if (ctx->rumble_expiration) {
|
||||
Uint32 now = SDL_GetTicks();
|
||||
if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
|
||||
HIDAPI_DriverXboxOne_Rumble(joystick, dev, context, 0, 0, 0);
|
||||
HIDAPI_DriverXboxOne_Rumble(context, joystick, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return (size >= 0);
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverXboxOne_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||
{
|
||||
SDL_free(context);
|
||||
}
|
||||
|
||||
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
|
||||
{
|
||||
SDL_HINT_JOYSTICK_HIDAPI_XBOX,
|
||||
SDL_TRUE,
|
||||
HIDAPI_DriverXboxOne_IsSupportedDevice,
|
||||
HIDAPI_DriverXboxOne_GetDeviceName,
|
||||
HIDAPI_DriverXboxOne_Init,
|
||||
HIDAPI_DriverXboxOne_Rumble,
|
||||
HIDAPI_DriverXboxOne_Update,
|
||||
HIDAPI_DriverXboxOne_Quit
|
||||
HIDAPI_DriverXboxOne_InitDriver,
|
||||
HIDAPI_DriverXboxOne_QuitDriver,
|
||||
HIDAPI_DriverXboxOne_UpdateDriver,
|
||||
HIDAPI_DriverXboxOne_NumJoysticks,
|
||||
HIDAPI_DriverXboxOne_InstanceIDForIndex,
|
||||
HIDAPI_DriverXboxOne_OpenJoystick,
|
||||
HIDAPI_DriverXboxOne_Rumble
|
||||
};
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
|
||||
|
|
|
@ -50,18 +50,10 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
struct joystick_hwdata
|
||||
{
|
||||
SDL_HIDAPI_DeviceDriver *driver;
|
||||
void *context;
|
||||
|
||||
SDL_mutex *mutex;
|
||||
hid_device *dev;
|
||||
};
|
||||
|
||||
typedef struct _SDL_HIDAPI_Device
|
||||
{
|
||||
SDL_JoystickID instance_id;
|
||||
SDL_HIDAPI_DriverData devdata;
|
||||
SDL_mutex *mutex;
|
||||
char *name;
|
||||
char *path;
|
||||
Uint16 vendor_id;
|
||||
|
@ -95,6 +87,9 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
|
|||
#ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
|
||||
&SDL_HIDAPI_DriverXboxOne,
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
|
||||
&SDL_HIDAPI_DriverGameCube,
|
||||
#endif
|
||||
};
|
||||
static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
|
||||
static int SDL_HIDAPI_numjoysticks = 0;
|
||||
|
@ -393,6 +388,36 @@ HIDAPI_ShutdownDiscovery()
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_InitDriver(SDL_HIDAPI_Device *device)
|
||||
{
|
||||
device->devdata.device = hid_open_path(device->path, 0);
|
||||
if (!device->devdata.device) {
|
||||
SDL_SetError("Couldn't open HID device %s", device->path);
|
||||
device->driver = NULL;
|
||||
} else {
|
||||
device->driver->InitDriver(
|
||||
&device->devdata,
|
||||
device->vendor_id,
|
||||
device->product_id,
|
||||
&SDL_HIDAPI_numjoysticks
|
||||
);
|
||||
device->mutex = SDL_CreateMutex();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_QuitDriver(SDL_HIDAPI_Device *device, SDL_bool send_event)
|
||||
{
|
||||
device->driver->QuitDriver(
|
||||
&device->devdata,
|
||||
send_event,
|
||||
&SDL_HIDAPI_numjoysticks
|
||||
);
|
||||
hid_close(device->devdata.device);
|
||||
SDL_DestroyMutex(device->mutex);
|
||||
device->driver = NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
HIDAPI_XboxControllerName(Uint16 vendor_id, Uint16 product_id)
|
||||
|
@ -605,15 +630,17 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
|
|||
}
|
||||
|
||||
static SDL_HIDAPI_Device *
|
||||
HIDAPI_GetJoystickByIndex(int device_index)
|
||||
HIDAPI_GetDeviceByIndex(int device_index)
|
||||
{
|
||||
SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
|
||||
int joysticks;
|
||||
while (device) {
|
||||
if (device->driver) {
|
||||
if (device_index == 0) {
|
||||
joysticks = device->driver->NumJoysticks(&device->devdata);
|
||||
if (device_index < joysticks) {
|
||||
break;
|
||||
}
|
||||
--device_index;
|
||||
device_index -= joysticks;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
|
@ -660,20 +687,12 @@ SDL_HIDAPIDriverHintChanged(void *userdata, const char *name, const char *oldVal
|
|||
while (device) {
|
||||
if (device->driver) {
|
||||
if (!device->driver->enabled) {
|
||||
device->driver = NULL;
|
||||
|
||||
--SDL_HIDAPI_numjoysticks;
|
||||
|
||||
SDL_PrivateJoystickRemoved(device->instance_id);
|
||||
HIDAPI_QuitDriver(device, SDL_TRUE);
|
||||
}
|
||||
} else {
|
||||
device->driver = HIDAPI_GetDeviceDriver(device);
|
||||
if (device->driver) {
|
||||
device->instance_id = SDL_GetNextJoystickInstanceID();
|
||||
|
||||
++SDL_HIDAPI_numjoysticks;
|
||||
|
||||
SDL_PrivateJoystickAdded(device->instance_id);
|
||||
HIDAPI_InitDriver(device);
|
||||
}
|
||||
}
|
||||
device = device->next;
|
||||
|
@ -723,7 +742,6 @@ HIDAPI_AddDevice(struct hid_device_info *info)
|
|||
if (!device) {
|
||||
return;
|
||||
}
|
||||
device->instance_id = -1;
|
||||
device->seen = SDL_TRUE;
|
||||
device->vendor_id = info->vendor_id;
|
||||
device->product_id = info->product_id;
|
||||
|
@ -818,12 +836,8 @@ HIDAPI_AddDevice(struct hid_device_info *info)
|
|||
}
|
||||
|
||||
if (device->driver) {
|
||||
/* It's a joystick! */
|
||||
device->instance_id = SDL_GetNextJoystickInstanceID();
|
||||
|
||||
++SDL_HIDAPI_numjoysticks;
|
||||
|
||||
SDL_PrivateJoystickAdded(device->instance_id);
|
||||
/* It's a joystick device! */
|
||||
HIDAPI_InitDriver(device);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -840,11 +854,8 @@ HIDAPI_DelDevice(SDL_HIDAPI_Device *device, SDL_bool send_event)
|
|||
SDL_HIDAPI_devices = curr->next;
|
||||
}
|
||||
|
||||
if (device->driver && send_event) {
|
||||
/* Need to decrement the joystick count before we post the event */
|
||||
--SDL_HIDAPI_numjoysticks;
|
||||
|
||||
SDL_PrivateJoystickRemoved(device->instance_id);
|
||||
if (device->driver) {
|
||||
HIDAPI_QuitDriver(device, send_event);
|
||||
}
|
||||
|
||||
SDL_free(device->name);
|
||||
|
@ -931,7 +942,7 @@ HIDAPI_JoystickDetect(void)
|
|||
static const char *
|
||||
HIDAPI_JoystickGetDeviceName(int device_index)
|
||||
{
|
||||
return HIDAPI_GetJoystickByIndex(device_index)->name;
|
||||
return HIDAPI_GetDeviceByIndex(device_index)->name;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -943,89 +954,61 @@ HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
|
|||
static SDL_JoystickGUID
|
||||
HIDAPI_JoystickGetDeviceGUID(int device_index)
|
||||
{
|
||||
return HIDAPI_GetJoystickByIndex(device_index)->guid;
|
||||
return HIDAPI_GetDeviceByIndex(device_index)->guid;
|
||||
}
|
||||
|
||||
static SDL_JoystickID
|
||||
HIDAPI_JoystickGetDeviceInstanceID(int device_index)
|
||||
{
|
||||
return HIDAPI_GetJoystickByIndex(device_index)->instance_id;
|
||||
SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
|
||||
int joysticks;
|
||||
while (device) {
|
||||
if (device->driver) {
|
||||
joysticks = device->driver->NumJoysticks(&device->devdata);
|
||||
if (device_index < joysticks) {
|
||||
break;
|
||||
}
|
||||
device_index -= joysticks;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
return device->driver->InstanceIDForIndex(&device->devdata, device_index);
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
SDL_HIDAPI_Device *device = HIDAPI_GetJoystickByIndex(device_index);
|
||||
struct joystick_hwdata *hwdata;
|
||||
SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index);
|
||||
|
||||
hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
|
||||
if (!hwdata) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
hwdata->driver = device->driver;
|
||||
hwdata->dev = hid_open_path(device->path, 0);
|
||||
if (!hwdata->dev) {
|
||||
SDL_free(hwdata);
|
||||
return SDL_SetError("Couldn't open HID device %s", device->path);
|
||||
}
|
||||
hwdata->mutex = SDL_CreateMutex();
|
||||
|
||||
if (!device->driver->Init(joystick, hwdata->dev, device->vendor_id, device->product_id, &hwdata->context)) {
|
||||
hid_close(hwdata->dev);
|
||||
SDL_free(hwdata);
|
||||
if (!device->driver->OpenJoystick(&device->devdata, joystick)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
joystick->hwdata = hwdata;
|
||||
joystick->hwdata = (struct joystick_hwdata *)device;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
{
|
||||
struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||
SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
|
||||
SDL_HIDAPI_Device *device = (SDL_HIDAPI_Device *)joystick->hwdata;
|
||||
int result;
|
||||
|
||||
SDL_LockMutex(hwdata->mutex);
|
||||
result = driver->Rumble(joystick, hwdata->dev, hwdata->context, low_frequency_rumble, high_frequency_rumble, duration_ms);
|
||||
SDL_UnlockMutex(hwdata->mutex);
|
||||
SDL_LockMutex(device->mutex);
|
||||
result = device->driver->Rumble(&device->devdata, joystick, low_frequency_rumble, high_frequency_rumble, duration_ms);
|
||||
SDL_UnlockMutex(device->mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||
SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
|
||||
SDL_bool succeeded;
|
||||
|
||||
SDL_LockMutex(hwdata->mutex);
|
||||
succeeded = driver->Update(joystick, hwdata->dev, hwdata->context);
|
||||
SDL_UnlockMutex(hwdata->mutex);
|
||||
|
||||
if (!succeeded) {
|
||||
SDL_HIDAPI_Device *device;
|
||||
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||
if (device->instance_id == joystick->instance_id) {
|
||||
HIDAPI_DelDevice(device, SDL_TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* No-op, all updates are done in SDL_HIDAPI_UpdateDevices */
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||
SDL_HIDAPI_DeviceDriver *driver = hwdata->driver;
|
||||
driver->Quit(joystick, hwdata->dev, hwdata->context);
|
||||
|
||||
hid_close(hwdata->dev);
|
||||
SDL_DestroyMutex(hwdata->mutex);
|
||||
SDL_free(hwdata);
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
|
@ -1050,6 +1033,30 @@ HIDAPI_JoystickQuit(void)
|
|||
hid_exit();
|
||||
}
|
||||
|
||||
void
|
||||
SDL_HIDAPI_UpdateDevices(void)
|
||||
{
|
||||
SDL_HIDAPI_Device *next, *device = SDL_HIDAPI_devices;
|
||||
SDL_bool succeeded;
|
||||
|
||||
while (device) {
|
||||
if (device->driver) {
|
||||
SDL_LockMutex(device->mutex);
|
||||
succeeded = device->driver->UpdateDriver(&device->devdata, &SDL_HIDAPI_numjoysticks);
|
||||
SDL_UnlockMutex(device->mutex);
|
||||
if (!succeeded) {
|
||||
next = device->next;
|
||||
HIDAPI_DelDevice(device, SDL_TRUE);
|
||||
device = next;
|
||||
} else {
|
||||
device = device->next;
|
||||
}
|
||||
} else {
|
||||
device = device->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
|
||||
{
|
||||
HIDAPI_JoystickInit,
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define SDL_JOYSTICK_HIDAPI_SWITCH
|
||||
#define SDL_JOYSTICK_HIDAPI_XBOX360
|
||||
#define SDL_JOYSTICK_HIDAPI_XBOXONE
|
||||
#define SDL_JOYSTICK_HIDAPI_GAMECUBE
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
/* On Windows, Xbox One controllers are handled by the Xbox 360 driver */
|
||||
|
@ -43,16 +44,36 @@
|
|||
#undef SDL_JOYSTICK_HIDAPI_XBOXONE
|
||||
#endif
|
||||
|
||||
typedef struct _SDL_HIDAPI_DriverData
|
||||
{
|
||||
hid_device *device;
|
||||
void *context;
|
||||
} SDL_HIDAPI_DriverData;
|
||||
|
||||
typedef struct _SDL_HIDAPI_DeviceDriver
|
||||
{
|
||||
const char *hint;
|
||||
SDL_bool enabled;
|
||||
SDL_bool (*IsSupportedDevice)(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number);
|
||||
const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id);
|
||||
SDL_bool (*Init)(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context);
|
||||
int (*Rumble)(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
|
||||
SDL_bool (*Update)(SDL_Joystick *joystick, hid_device *dev, void *context);
|
||||
void (*Quit)(SDL_Joystick *joystick, hid_device *dev, void *context);
|
||||
|
||||
SDL_bool (*InitDriver)(SDL_HIDAPI_DriverData *context,
|
||||
Uint16 vendor_id, Uint16 product_id, int *num_joysticks);
|
||||
void (*QuitDriver)(SDL_HIDAPI_DriverData *context,
|
||||
SDL_bool send_event,
|
||||
int *num_joysticks);
|
||||
SDL_bool (*UpdateDriver)(SDL_HIDAPI_DriverData *context,
|
||||
int *num_joysticks);
|
||||
int (*NumJoysticks)(SDL_HIDAPI_DriverData *context);
|
||||
SDL_JoystickID (*InstanceIDForIndex)(SDL_HIDAPI_DriverData *context,
|
||||
int index);
|
||||
SDL_bool (*OpenJoystick)(SDL_HIDAPI_DriverData *context,
|
||||
SDL_Joystick *joystick);
|
||||
int (*Rumble)(SDL_HIDAPI_DriverData *context,
|
||||
SDL_Joystick *joystick,
|
||||
Uint16 low_frequency_rumble,
|
||||
Uint16 high_frequency_rumble,
|
||||
Uint32 duration_ms);
|
||||
|
||||
} SDL_HIDAPI_DeviceDriver;
|
||||
|
||||
|
@ -62,6 +83,7 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam;
|
|||
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch;
|
||||
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360;
|
||||
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne;
|
||||
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube;
|
||||
|
||||
/* Return true if a HID device is present and supported as a joystick */
|
||||
extern SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version);
|
||||
|
|
Loading…
Reference in New Issue