mirror of
https://github.com/encounter/SDL.git
synced 2025-12-16 16:37:09 +00:00
Added HIDAPI joystick drivers for more consistent support for Xbox, PS4 and Nintendo Switch Pro controller support across platforms.
Added SDL_GameControllerRumble() and SDL_JoystickRumble() for simple force feedback outside of the SDL haptics API
This commit is contained in:
@@ -33,7 +33,6 @@
|
||||
#include "SDL_stdinc.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "../steam/SDL_steamcontroller.h"
|
||||
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
@@ -59,7 +58,6 @@ static CMMotionManager *motionManager = nil;
|
||||
static SDL_JoystickDeviceItem *deviceList = NULL;
|
||||
|
||||
static int numjoysticks = 0;
|
||||
static SDL_JoystickID instancecounter = 0;
|
||||
int SDL_AppleTVRemoteOpenedAsJoystick = 0;
|
||||
|
||||
static SDL_JoystickDeviceItem *
|
||||
@@ -80,10 +78,9 @@ GetDeviceForIndex(int device_index)
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
|
||||
IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
const Uint16 BUS_BLUETOOTH = 0x05;
|
||||
const Uint16 VENDOR_APPLE = 0x05AC;
|
||||
Uint16 *guid16 = (Uint16 *)device->guid.data;
|
||||
Uint16 vendor = 0;
|
||||
@@ -136,7 +133,7 @@ SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *contr
|
||||
|
||||
/* We only need 16 bits for each of these; space them out to fill 128. */
|
||||
/* Byteswap so devices get same GUID on little/big endian platforms. */
|
||||
*guid16++ = SDL_SwapLE16(BUS_BLUETOOTH);
|
||||
*guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH);
|
||||
*guid16++ = 0;
|
||||
*guid16++ = SDL_SwapLE16(vendor);
|
||||
*guid16++ = 0;
|
||||
@@ -157,7 +154,7 @@ SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *contr
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
|
||||
IOS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
|
||||
@@ -183,7 +180,7 @@ SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
|
||||
}
|
||||
|
||||
device->accelerometer = accelerometer;
|
||||
device->instance_id = instancecounter++;
|
||||
device->instance_id = SDL_GetNextJoystickInstanceID();
|
||||
|
||||
if (accelerometer) {
|
||||
#if TARGET_OS_TV
|
||||
@@ -199,7 +196,7 @@ SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
|
||||
SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
|
||||
#endif /* TARGET_OS_TV */
|
||||
} else if (controller) {
|
||||
SDL_SYS_AddMFIJoystickDevice(device, controller);
|
||||
IOS_AddMFIJoystickDevice(device, controller);
|
||||
}
|
||||
|
||||
if (deviceList == NULL) {
|
||||
@@ -214,11 +211,11 @@ SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
|
||||
|
||||
++numjoysticks;
|
||||
|
||||
SDL_PrivateJoystickAdded(numjoysticks - 1);
|
||||
SDL_PrivateJoystickAdded(device->instance_id);
|
||||
}
|
||||
|
||||
static SDL_JoystickDeviceItem *
|
||||
SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
|
||||
IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
|
||||
{
|
||||
SDL_JoystickDeviceItem *prev = NULL;
|
||||
SDL_JoystickDeviceItem *next = NULL;
|
||||
@@ -287,78 +284,27 @@ SDL_AppleTVRemoteRotationHintChanged(void *udata, const char *name, const char *
|
||||
}
|
||||
#endif /* TARGET_OS_TV */
|
||||
|
||||
static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = (SDL_JoystickDeviceItem *)SDL_calloc(1, sizeof(SDL_JoystickDeviceItem));
|
||||
if (device == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
*device_instance = device->instance_id = instancecounter++;
|
||||
device->name = SDL_strdup(name);
|
||||
device->guid = guid;
|
||||
SDL_GetSteamControllerInputs(&device->nbuttons,
|
||||
&device->naxes,
|
||||
&device->nhats);
|
||||
device->m_bSteamController = SDL_TRUE;
|
||||
|
||||
if (deviceList == NULL) {
|
||||
deviceList = device;
|
||||
} else {
|
||||
SDL_JoystickDeviceItem *lastdevice = deviceList;
|
||||
while (lastdevice->next != NULL) {
|
||||
lastdevice = lastdevice->next;
|
||||
}
|
||||
lastdevice->next = device;
|
||||
}
|
||||
|
||||
++numjoysticks;
|
||||
|
||||
SDL_PrivateJoystickAdded(numjoysticks - 1);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static void SteamControllerDisconnectedCallback(int device_instance)
|
||||
{
|
||||
SDL_JoystickDeviceItem *item;
|
||||
|
||||
for (item = deviceList; item; item = item->next) {
|
||||
if (item->instance_id == device_instance) {
|
||||
SDL_SYS_RemoveJoystickDevice(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
static int
|
||||
IOS_JoystickInit(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
SDL_InitSteamControllers(SteamControllerConnectedCallback,
|
||||
SteamControllerDisconnectedCallback);
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
SDL_SYS_AddJoystickDevice(nil, SDL_TRUE);
|
||||
IOS_AddJoystickDevice(nil, SDL_TRUE);
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
/* GameController.framework was added in iOS 7. */
|
||||
if (![GCController class]) {
|
||||
return numjoysticks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (GCController *controller in [GCController controllers]) {
|
||||
SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
IOS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
}
|
||||
|
||||
#if TARGET_OS_TV
|
||||
@@ -371,7 +317,7 @@ SDL_SYS_JoystickInit(void)
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
GCController *controller = note.object;
|
||||
SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
IOS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
}];
|
||||
|
||||
disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
|
||||
@@ -382,7 +328,7 @@ SDL_SYS_JoystickInit(void)
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
while (device != NULL) {
|
||||
if (device->controller == controller) {
|
||||
SDL_SYS_RemoveJoystickDevice(device);
|
||||
IOS_RemoveJoystickDevice(device);
|
||||
break;
|
||||
}
|
||||
device = device->next;
|
||||
@@ -391,43 +337,49 @@ SDL_SYS_JoystickInit(void)
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
}
|
||||
|
||||
return numjoysticks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_NumJoysticks(void)
|
||||
static int
|
||||
IOS_JoystickGetCount(void)
|
||||
{
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_JoystickDetect(void)
|
||||
static void
|
||||
IOS_JoystickDetect(void)
|
||||
{
|
||||
SDL_UpdateSteamControllers();
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
static const char *
|
||||
IOS_JoystickGetDeviceName(int device_index)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
return device ? device->name : "Unknown";
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
static SDL_JoystickGUID
|
||||
IOS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
return device ? device->instance_id : 0;
|
||||
SDL_JoystickGUID guid;
|
||||
if (device) {
|
||||
guid = device->guid;
|
||||
} else {
|
||||
SDL_zero(guid);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
static SDL_JoystickID
|
||||
IOS_JoystickGetDeviceInstanceID(int device_index)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
return device ? device->instance_id : -1;
|
||||
}
|
||||
|
||||
static int
|
||||
IOS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
if (device == NULL) {
|
||||
@@ -473,15 +425,14 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to determine if this joystick is attached to the system right now */
|
||||
SDL_bool
|
||||
SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
static SDL_bool
|
||||
IOS_JoystickIsAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return joystick->hwdata != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
IOS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
const float maxgforce = SDL_IPHONE_MAX_GFORCE;
|
||||
@@ -526,7 +477,7 @@ SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
static Uint8
|
||||
SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
|
||||
IOS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
|
||||
{
|
||||
Uint8 hat = 0;
|
||||
|
||||
@@ -551,7 +502,7 @@ SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
|
||||
#endif
|
||||
|
||||
static void
|
||||
SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
|
||||
IOS_MFIJoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
#if SDL_JOYSTICK_MFI
|
||||
@autoreleasepool {
|
||||
@@ -581,7 +532,7 @@ SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
|
||||
gamepad.rightShoulder.isPressed,
|
||||
};
|
||||
|
||||
hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(axes); i++) {
|
||||
/* The triggers (axes 2 and 5) are resting at -32768 but SDL
|
||||
@@ -608,7 +559,7 @@ SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
|
||||
gamepad.rightShoulder.isPressed,
|
||||
};
|
||||
|
||||
hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(buttons); i++) {
|
||||
updateplayerindex |= (joystick->buttons[i] != buttons[i]);
|
||||
@@ -678,13 +629,14 @@ SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
static int
|
||||
IOS_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
static void
|
||||
IOS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = joystick->hwdata;
|
||||
|
||||
@@ -692,21 +644,15 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->m_bSteamController) {
|
||||
SDL_UpdateSteamController(joystick);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->accelerometer) {
|
||||
SDL_SYS_AccelerometerUpdate(joystick);
|
||||
IOS_AccelerometerUpdate(joystick);
|
||||
} else if (device->controller) {
|
||||
SDL_SYS_MFIJoystickUpdate(joystick);
|
||||
IOS_MFIJoystickUpdate(joystick);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
static void
|
||||
IOS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = joystick->hwdata;
|
||||
|
||||
@@ -734,9 +680,8 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
static void
|
||||
IOS_JoystickQuit(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
@@ -759,7 +704,7 @@ SDL_SYS_JoystickQuit(void)
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
|
||||
while (deviceList != NULL) {
|
||||
SDL_SYS_RemoveJoystickDevice(deviceList);
|
||||
IOS_RemoveJoystickDevice(deviceList);
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
@@ -767,34 +712,23 @@ SDL_SYS_JoystickQuit(void)
|
||||
#endif /* !TARGET_OS_TV */
|
||||
}
|
||||
|
||||
SDL_QuitSteamControllers();
|
||||
|
||||
numjoysticks = 0;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID
|
||||
SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
SDL_JoystickDriver SDL_IOS_JoystickDriver =
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
SDL_JoystickGUID guid;
|
||||
if (device) {
|
||||
guid = device->guid;
|
||||
} else {
|
||||
SDL_zero(guid);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID
|
||||
SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
if (joystick->hwdata) {
|
||||
guid = joystick->hwdata->guid;
|
||||
} else {
|
||||
SDL_zero(guid);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
IOS_JoystickInit,
|
||||
IOS_JoystickGetCount,
|
||||
IOS_JoystickDetect,
|
||||
IOS_JoystickGetDeviceName,
|
||||
IOS_JoystickGetDeviceGUID,
|
||||
IOS_JoystickGetDeviceInstanceID,
|
||||
IOS_JoystickOpen,
|
||||
IOS_JoystickIsAttached,
|
||||
IOS_JoystickRumble,
|
||||
IOS_JoystickUpdate,
|
||||
IOS_JoystickClose,
|
||||
IOS_JoystickQuit,
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -46,9 +46,6 @@ typedef struct joystick_hwdata
|
||||
int nbuttons;
|
||||
int nhats;
|
||||
|
||||
/* Steam Controller support */
|
||||
SDL_bool m_bSteamController;
|
||||
|
||||
struct joystick_hwdata *next;
|
||||
} joystick_hwdata;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user