2015-06-21 17:33:46 +02:00
/*
Simple DirectMedia Layer
2018-01-03 19:03:25 +01:00
Copyright ( C ) 1997 - 2018 Sam Lantinga < slouken @ libsdl . org >
2015-06-21 17:33:46 +02:00
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"
/* This is the joystick API for Simple DirectMedia Layer */
# include "SDL.h"
2018-08-10 01:00:17 +02:00
# include "SDL_atomic.h"
2015-06-21 17:33:46 +02:00
# include "SDL_events.h"
# include "SDL_sysjoystick.h"
# include "SDL_assert.h"
# include "SDL_hints.h"
# if !SDL_EVENTS_DISABLED
# include "../events/SDL_events_c.h"
# endif
2017-08-13 02:41:59 +02:00
# include "../video/SDL_sysvideo.h"
2015-06-21 17:33:46 +02:00
2018-08-10 01:00:17 +02:00
/* This is included in only one place because it has a large static list of controllers */
# include "controller_type.h"
2017-01-27 14:59:58 +01:00
2018-08-10 01:00:17 +02:00
# ifdef __WIN32__
/* Needed for checking for input remapping programs */
2018-08-10 01:03:29 +02:00
# include "../core/windows/SDL_windows.h"
2018-08-10 01:00:17 +02:00
# undef UNICODE /* We want ASCII functions */
# include <tlhelp32.h>
# endif
static SDL_JoystickDriver * SDL_joystick_drivers [ ] = {
# if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
& SDL_WINDOWS_JoystickDriver ,
# endif
# ifdef SDL_JOYSTICK_LINUX
& SDL_LINUX_JoystickDriver ,
# endif
# ifdef SDL_JOYSTICK_IOKIT
& SDL_DARWIN_JoystickDriver ,
# endif
# if defined(__IPHONEOS__) || defined(__TVOS__)
& SDL_IOS_JoystickDriver ,
# endif
# ifdef SDL_JOYSTICK_ANDROID
& SDL_ANDROID_JoystickDriver ,
# endif
2018-08-10 20:32:30 +02:00
# ifdef SDL_JOYSTICK_EMSCRIPTEN
& SDL_EMSCRIPTEN_JoystickDriver ,
# endif
2018-08-10 21:04:08 +02:00
# ifdef SDL_JOYSTICK_HAIKU
& SDL_HAIKU_JoystickDriver ,
# endif
2018-08-10 20:42:40 +02:00
# ifdef SDL_JOYSTICK_USBHID /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */
& SDL_BSD_JoystickDriver ,
# endif
2018-08-10 01:00:17 +02:00
# ifdef SDL_JOYSTICK_HIDAPI
& SDL_HIDAPI_JoystickDriver ,
# endif
# if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
& SDL_DUMMY_JoystickDriver
# endif
} ;
2015-06-21 17:33:46 +02:00
static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE ;
static SDL_Joystick * SDL_joysticks = NULL ;
2016-12-14 15:25:09 +01:00
static SDL_bool SDL_updating_joystick = SDL_FALSE ;
2016-11-29 14:04:42 +01:00
static SDL_mutex * SDL_joystick_lock = NULL ; /* This needs to support recursive locks */
2018-08-10 01:00:17 +02:00
static SDL_atomic_t SDL_next_joystick_instance_id ;
2016-11-29 14:04:42 +01:00
2016-12-08 19:13:45 +01:00
void
2017-10-10 20:10:15 +02:00
SDL_LockJoysticks ( void )
2016-11-29 14:04:42 +01:00
{
if ( SDL_joystick_lock ) {
SDL_LockMutex ( SDL_joystick_lock ) ;
}
}
2016-12-08 19:13:45 +01:00
void
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( void )
2016-11-29 14:04:42 +01:00
{
if ( SDL_joystick_lock ) {
SDL_UnlockMutex ( SDL_joystick_lock ) ;
}
}
2015-06-21 17:33:46 +02:00
2017-08-14 15:28:21 +02:00
static void SDLCALL
2015-06-21 17:33:46 +02:00
SDL_JoystickAllowBackgroundEventsChanged ( void * userdata , const char * name , const char * oldValue , const char * hint )
{
if ( hint & & * hint = = ' 1 ' ) {
SDL_joystick_allows_background_events = SDL_TRUE ;
} else {
SDL_joystick_allows_background_events = SDL_FALSE ;
}
}
int
SDL_JoystickInit ( void )
{
2018-08-10 01:00:17 +02:00
int i , status ;
2015-06-21 17:33:46 +02:00
2017-08-09 20:59:29 +02:00
SDL_GameControllerInitMappings ( ) ;
2016-11-29 14:04:42 +01:00
/* Create the joystick list lock */
if ( ! SDL_joystick_lock ) {
SDL_joystick_lock = SDL_CreateMutex ( ) ;
}
2015-06-21 17:33:46 +02:00
/* See if we should allow joystick events while in the background */
SDL_AddHintCallback ( SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS ,
SDL_JoystickAllowBackgroundEventsChanged , NULL ) ;
# if !SDL_EVENTS_DISABLED
if ( SDL_InitSubSystem ( SDL_INIT_EVENTS ) < 0 ) {
return - 1 ;
}
# endif /* !SDL_EVENTS_DISABLED */
2018-08-10 01:00:17 +02:00
status = - 1 ;
for ( i = 0 ; i < SDL_arraysize ( SDL_joystick_drivers ) ; + + i ) {
if ( SDL_joystick_drivers [ i ] - > Init ( ) > = 0 ) {
status = 0 ;
}
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
return status ;
2015-06-21 17:33:46 +02:00
}
/*
* Count the number of joysticks attached to the system
*/
int
SDL_NumJoysticks ( void )
{
2018-08-10 01:00:17 +02:00
int i , total_joysticks = 0 ;
SDL_LockJoysticks ( ) ;
for ( i = 0 ; i < SDL_arraysize ( SDL_joystick_drivers ) ; + + i ) {
total_joysticks + = SDL_joystick_drivers [ i ] - > GetCount ( ) ;
}
SDL_UnlockJoysticks ( ) ;
return total_joysticks ;
}
/*
* Return the next available joystick instance ID
* This may be called by drivers from multiple threads , unprotected by any locks
*/
SDL_JoystickID SDL_GetNextJoystickInstanceID ( )
{
return SDL_AtomicIncRef ( & SDL_next_joystick_instance_id ) ;
}
/*
* Get the driver and device index for an API device index
* This should be called while the joystick lock is held , to prevent another thread from updating the list
*/
SDL_bool
SDL_GetDriverAndJoystickIndex ( int device_index , SDL_JoystickDriver * * driver , int * driver_index )
{
int i , num_joysticks , total_joysticks = 0 ;
if ( device_index > = 0 ) {
for ( i = 0 ; i < SDL_arraysize ( SDL_joystick_drivers ) ; + + i ) {
num_joysticks = SDL_joystick_drivers [ i ] - > GetCount ( ) ;
if ( device_index < num_joysticks ) {
* driver = SDL_joystick_drivers [ i ] ;
* driver_index = device_index ;
return SDL_TRUE ;
}
device_index - = num_joysticks ;
total_joysticks + = num_joysticks ;
}
}
SDL_SetError ( " There are %d joysticks available " , total_joysticks ) ;
return SDL_FALSE ;
2015-06-21 17:33:46 +02:00
}
2018-03-06 23:51:50 +01:00
/*
* Perform any needed fixups for joystick names
*/
static const char *
SDL_FixupJoystickName ( const char * name )
{
if ( name ) {
const char * skip_prefix = " NVIDIA Corporation " ;
if ( SDL_strncmp ( name , skip_prefix , SDL_strlen ( skip_prefix ) ) = = 0 ) {
name + = SDL_strlen ( skip_prefix ) ;
}
}
return name ;
}
2015-06-21 17:33:46 +02:00
/*
* Get the implementation dependent name of a joystick
*/
const char *
SDL_JoystickNameForIndex ( int device_index )
{
2018-08-10 01:00:17 +02:00
SDL_JoystickDriver * driver ;
const char * name = NULL ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
name = SDL_FixupJoystickName ( driver - > GetDeviceName ( device_index ) ) ;
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
SDL_UnlockJoysticks ( ) ;
/* FIXME: Really we should reference count this name so it doesn't go away after unlock */
return name ;
2015-06-21 17:33:46 +02:00
}
2018-10-26 01:53:14 +02:00
int
SDL_JoystickGetDevicePlayerIndex ( int device_index )
{
SDL_JoystickDriver * driver ;
int player_index = - 1 ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
player_index = driver - > GetDevicePlayerIndex ( device_index ) ;
}
SDL_UnlockJoysticks ( ) ;
return player_index ;
}
2017-01-04 08:39:28 +01:00
/*
* Return true if this joystick is known to have all axes centered at zero
* This isn ' t generally needed unless the joystick never generates an initial axis value near zero ,
* e . g . it ' s emulating axes with digital buttons
*/
static SDL_bool
SDL_JoystickAxesCenteredAtZero ( SDL_Joystick * joystick )
{
2017-01-27 14:59:58 +01:00
static Uint32 zero_centered_joysticks [ ] = {
MAKE_VIDPID ( 0x0e8f , 0x3013 ) , /* HuiJia SNES USB adapter */
MAKE_VIDPID ( 0x05a0 , 0x3232 ) , /* 8Bitdo Zero Gamepad */
2017-01-04 08:39:28 +01:00
} ;
int i ;
2017-01-27 14:59:58 +01:00
Uint32 id = MAKE_VIDPID ( SDL_JoystickGetVendor ( joystick ) ,
SDL_JoystickGetProduct ( joystick ) ) ;
2017-01-04 08:39:28 +01:00
2017-01-20 17:13:23 +01:00
/*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/
2017-01-04 16:06:48 +01:00
if ( joystick - > naxes = = 2 ) {
/* Assume D-pad or thumbstick style axes are centered at 0 */
return SDL_TRUE ;
}
2017-01-04 08:39:28 +01:00
for ( i = 0 ; i < SDL_arraysize ( zero_centered_joysticks ) ; + + i ) {
2017-01-27 14:59:58 +01:00
if ( id = = zero_centered_joysticks [ i ] ) {
2017-01-04 08:39:28 +01:00
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2015-06-21 17:33:46 +02:00
/*
* Open a joystick for use - the index passed as an argument refers to
* the N ' th joystick on the system . This index is the value which will
* identify this joystick in future joystick events .
*
* This function returns a joystick identifier , or NULL if an error occurred .
*/
SDL_Joystick *
SDL_JoystickOpen ( int device_index )
{
2018-08-10 01:00:17 +02:00
SDL_JoystickDriver * driver ;
SDL_JoystickID instance_id ;
2015-06-21 17:33:46 +02:00
SDL_Joystick * joystick ;
SDL_Joystick * joysticklist ;
const char * joystickname = NULL ;
2017-10-10 20:10:15 +02:00
SDL_LockJoysticks ( ) ;
2016-11-29 14:04:42 +01:00
2018-08-10 01:00:17 +02:00
if ( ! SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
SDL_UnlockJoysticks ( ) ;
return NULL ;
}
2015-06-21 17:33:46 +02:00
joysticklist = SDL_joysticks ;
/* If the joystick is already open, return it
2017-03-10 01:09:16 +01:00
* it is important that we have a single joystick * for each instance id
*/
2018-08-10 01:00:17 +02:00
instance_id = driver - > GetDeviceInstanceID ( device_index ) ;
2015-06-21 17:33:46 +02:00
while ( joysticklist ) {
2018-08-10 01:00:17 +02:00
if ( instance_id = = joysticklist - > instance_id ) {
2015-06-21 17:33:46 +02:00
joystick = joysticklist ;
+ + joystick - > ref_count ;
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2018-08-10 01:00:17 +02:00
return joystick ;
2015-06-21 17:33:46 +02:00
}
joysticklist = joysticklist - > next ;
}
/* Create and initialize the joystick */
2017-01-27 14:59:58 +01:00
joystick = ( SDL_Joystick * ) SDL_calloc ( sizeof ( * joystick ) , 1 ) ;
2015-06-21 17:33:46 +02:00
if ( joystick = = NULL ) {
SDL_OutOfMemory ( ) ;
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
return NULL ;
}
2018-08-10 01:00:17 +02:00
joystick - > driver = driver ;
joystick - > instance_id = instance_id ;
2018-08-10 01:03:50 +02:00
joystick - > attached = SDL_TRUE ;
2018-10-26 01:53:14 +02:00
joystick - > player_index = - 1 ;
2015-06-21 17:33:46 +02:00
2018-08-10 01:00:17 +02:00
if ( driver - > Open ( joystick , device_index ) < 0 ) {
2015-06-21 17:33:46 +02:00
SDL_free ( joystick ) ;
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
return NULL ;
}
2018-08-10 01:00:17 +02:00
joystickname = driver - > GetDeviceName ( device_index ) ;
if ( joystickname ) {
2015-06-21 17:33:46 +02:00
joystick - > name = SDL_strdup ( joystickname ) ;
2018-08-10 01:00:17 +02:00
} else {
2015-06-21 17:33:46 +02:00
joystick - > name = NULL ;
2018-08-10 01:00:17 +02:00
}
joystick - > guid = driver - > GetDeviceGUID ( device_index ) ;
2015-06-21 17:33:46 +02:00
if ( joystick - > naxes > 0 ) {
2016-12-23 02:33:45 +01:00
joystick - > axes = ( SDL_JoystickAxisInfo * ) SDL_calloc ( joystick - > naxes , sizeof ( SDL_JoystickAxisInfo ) ) ;
2015-06-21 17:33:46 +02:00
}
if ( joystick - > nhats > 0 ) {
2016-12-23 02:33:45 +01:00
joystick - > hats = ( Uint8 * ) SDL_calloc ( joystick - > nhats , sizeof ( Uint8 ) ) ;
2015-06-21 17:33:46 +02:00
}
if ( joystick - > nballs > 0 ) {
2016-12-23 02:33:45 +01:00
joystick - > balls = ( struct balldelta * ) SDL_calloc ( joystick - > nballs , sizeof ( * joystick - > balls ) ) ;
2015-06-21 17:33:46 +02:00
}
if ( joystick - > nbuttons > 0 ) {
2016-12-23 02:33:45 +01:00
joystick - > buttons = ( Uint8 * ) SDL_calloc ( joystick - > nbuttons , sizeof ( Uint8 ) ) ;
2015-06-21 17:33:46 +02:00
}
if ( ( ( joystick - > naxes > 0 ) & & ! joystick - > axes )
| | ( ( joystick - > nhats > 0 ) & & ! joystick - > hats )
| | ( ( joystick - > nballs > 0 ) & & ! joystick - > balls )
| | ( ( joystick - > nbuttons > 0 ) & & ! joystick - > buttons ) ) {
SDL_OutOfMemory ( ) ;
SDL_JoystickClose ( joystick ) ;
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
return NULL ;
}
2015-10-01 00:39:30 +02:00
joystick - > epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN ;
2015-06-21 17:33:46 +02:00
2017-01-04 08:39:28 +01:00
/* If this joystick is known to have all zero centered axes, skip the auto-centering code */
if ( SDL_JoystickAxesCenteredAtZero ( joystick ) ) {
int i ;
for ( i = 0 ; i < joystick - > naxes ; + + i ) {
joystick - > axes [ i ] . has_initial_value = SDL_TRUE ;
}
}
2017-01-27 14:59:58 +01:00
joystick - > is_game_controller = SDL_IsGameController ( device_index ) ;
2015-06-21 17:33:46 +02:00
/* Add joystick to list */
+ + joystick - > ref_count ;
/* Link the joystick in the list */
joystick - > next = SDL_joysticks ;
SDL_joysticks = joystick ;
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2016-11-29 14:04:42 +01:00
2018-08-10 01:00:17 +02:00
driver - > Update ( joystick ) ;
2016-12-08 19:13:45 +01:00
2018-08-10 01:00:17 +02:00
return joystick ;
2015-06-21 17:33:46 +02:00
}
/*
* Checks to make sure the joystick is valid .
*/
int
SDL_PrivateJoystickValid ( SDL_Joystick * joystick )
{
int valid ;
if ( joystick = = NULL ) {
SDL_SetError ( " Joystick hasn't been opened yet " ) ;
valid = 0 ;
} else {
valid = 1 ;
}
return valid ;
}
/*
* Get the number of multi - dimensional axis controls on a joystick
*/
int
SDL_JoystickNumAxes ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return - 1 ;
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
return joystick - > naxes ;
2015-06-21 17:33:46 +02:00
}
/*
* Get the number of hats on a joystick
*/
int
SDL_JoystickNumHats ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return - 1 ;
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
return joystick - > nhats ;
2015-06-21 17:33:46 +02:00
}
/*
* Get the number of trackballs on a joystick
*/
int
SDL_JoystickNumBalls ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return - 1 ;
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
return joystick - > nballs ;
2015-06-21 17:33:46 +02:00
}
/*
* Get the number of buttons on a joystick
*/
int
SDL_JoystickNumButtons ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return - 1 ;
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
return joystick - > nbuttons ;
2015-06-21 17:33:46 +02:00
}
/*
* Get the current state of an axis control on a joystick
*/
Sint16
SDL_JoystickGetAxis ( SDL_Joystick * joystick , int axis )
{
Sint16 state ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return 0 ;
2015-06-21 17:33:46 +02:00
}
if ( axis < joystick - > naxes ) {
2016-12-23 02:33:45 +01:00
state = joystick - > axes [ axis ] . value ;
2015-06-21 17:33:46 +02:00
} else {
SDL_SetError ( " Joystick only has %d axes " , joystick - > naxes ) ;
state = 0 ;
}
2018-08-10 01:00:17 +02:00
return state ;
2015-06-21 17:33:46 +02:00
}
2017-01-04 19:28:07 +01:00
/*
* Get the initial state of an axis control on a joystick
*/
SDL_bool
SDL_JoystickGetAxisInitialState ( SDL_Joystick * joystick , int axis , Sint16 * state )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return SDL_FALSE ;
}
if ( axis > = joystick - > naxes ) {
SDL_SetError ( " Joystick only has %d axes " , joystick - > naxes ) ;
return SDL_FALSE ;
}
if ( state ) {
* state = joystick - > axes [ axis ] . initial_value ;
}
return joystick - > axes [ axis ] . has_initial_value ;
}
2015-06-21 17:33:46 +02:00
/*
* Get the current state of a hat on a joystick
*/
Uint8
SDL_JoystickGetHat ( SDL_Joystick * joystick , int hat )
{
Uint8 state ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return 0 ;
2015-06-21 17:33:46 +02:00
}
if ( hat < joystick - > nhats ) {
state = joystick - > hats [ hat ] ;
} else {
SDL_SetError ( " Joystick only has %d hats " , joystick - > nhats ) ;
state = 0 ;
}
2018-08-10 01:00:17 +02:00
return state ;
2015-06-21 17:33:46 +02:00
}
/*
* Get the ball axis change since the last poll
*/
int
SDL_JoystickGetBall ( SDL_Joystick * joystick , int ball , int * dx , int * dy )
{
int retval ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return - 1 ;
2015-06-21 17:33:46 +02:00
}
retval = 0 ;
if ( ball < joystick - > nballs ) {
if ( dx ) {
* dx = joystick - > balls [ ball ] . dx ;
}
if ( dy ) {
* dy = joystick - > balls [ ball ] . dy ;
}
joystick - > balls [ ball ] . dx = 0 ;
joystick - > balls [ ball ] . dy = 0 ;
} else {
return SDL_SetError ( " Joystick only has %d balls " , joystick - > nballs ) ;
}
2018-08-10 01:00:17 +02:00
return retval ;
2015-06-21 17:33:46 +02:00
}
/*
* Get the current state of a button on a joystick
*/
Uint8
SDL_JoystickGetButton ( SDL_Joystick * joystick , int button )
{
Uint8 state ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return 0 ;
2015-06-21 17:33:46 +02:00
}
if ( button < joystick - > nbuttons ) {
state = joystick - > buttons [ button ] ;
} else {
SDL_SetError ( " Joystick only has %d buttons " , joystick - > nbuttons ) ;
state = 0 ;
}
2018-08-10 01:00:17 +02:00
return state ;
2015-06-21 17:33:46 +02:00
}
/*
* Return if the joystick in question is currently attached to the system ,
* \ return SDL_FALSE if not plugged in , SDL_TRUE if still present .
*/
SDL_bool
SDL_JoystickGetAttached ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return SDL_FALSE ;
}
2018-08-10 01:03:50 +02:00
return joystick - > attached ;
2015-06-21 17:33:46 +02:00
}
/*
* Get the instance id for this opened joystick
*/
SDL_JoystickID
SDL_JoystickInstanceID ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return - 1 ;
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
return joystick - > instance_id ;
2015-06-21 17:33:46 +02:00
}
2015-11-14 18:35:45 +01:00
/*
* Find the SDL_Joystick that owns this instance id
*/
SDL_Joystick *
SDL_JoystickFromInstanceID ( SDL_JoystickID joyid )
{
2016-11-29 14:04:42 +01:00
SDL_Joystick * joystick ;
2017-10-10 20:10:15 +02:00
SDL_LockJoysticks ( ) ;
2016-11-29 14:04:42 +01:00
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
2015-11-14 18:35:45 +01:00
if ( joystick - > instance_id = = joyid ) {
2018-08-21 06:18:56 +02:00
break ;
2015-11-14 18:35:45 +01:00
}
}
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2018-08-21 06:18:56 +02:00
return joystick ;
2015-11-14 18:35:45 +01:00
}
2015-06-21 17:33:46 +02:00
/*
* Get the friendly name of this joystick
*/
const char *
SDL_JoystickName ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return NULL ;
2015-06-21 17:33:46 +02:00
}
2018-03-06 23:51:50 +01:00
return SDL_FixupJoystickName ( joystick - > name ) ;
2015-06-21 17:33:46 +02:00
}
2018-10-26 01:53:14 +02:00
int
SDL_JoystickGetPlayerIndex ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return - 1 ;
}
return joystick - > player_index ;
}
2018-08-10 01:00:17 +02:00
int
SDL_JoystickRumble ( SDL_Joystick * joystick , Uint16 low_frequency_rumble , Uint16 high_frequency_rumble , Uint32 duration_ms )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return - 1 ;
}
return joystick - > driver - > Rumble ( joystick , low_frequency_rumble , high_frequency_rumble , duration_ms ) ;
}
2015-06-21 17:33:46 +02:00
/*
* Close a joystick previously opened with SDL_JoystickOpen ( )
*/
void
SDL_JoystickClose ( SDL_Joystick * joystick )
{
SDL_Joystick * joysticklist ;
SDL_Joystick * joysticklistprev ;
2018-08-10 01:00:17 +02:00
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2015-06-21 17:33:46 +02:00
return ;
}
2017-10-10 20:10:15 +02:00
SDL_LockJoysticks ( ) ;
2016-11-29 14:04:42 +01:00
2015-06-21 17:33:46 +02:00
/* First decrement ref count */
if ( - - joystick - > ref_count > 0 ) {
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
return ;
}
2016-12-14 15:25:09 +01:00
if ( SDL_updating_joystick ) {
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
return ;
}
2018-08-10 01:00:17 +02:00
joystick - > driver - > Close ( joystick ) ;
2015-06-21 17:33:46 +02:00
joystick - > hwdata = NULL ;
joysticklist = SDL_joysticks ;
joysticklistprev = NULL ;
while ( joysticklist ) {
if ( joystick = = joysticklist ) {
if ( joysticklistprev ) {
/* unlink this entry */
joysticklistprev - > next = joysticklist - > next ;
} else {
SDL_joysticks = joystick - > next ;
}
break ;
}
joysticklistprev = joysticklist ;
joysticklist = joysticklist - > next ;
}
SDL_free ( joystick - > name ) ;
/* Free the data associated with this joystick */
SDL_free ( joystick - > axes ) ;
SDL_free ( joystick - > hats ) ;
SDL_free ( joystick - > balls ) ;
SDL_free ( joystick - > buttons ) ;
SDL_free ( joystick ) ;
2016-11-29 14:04:42 +01:00
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
}
void
SDL_JoystickQuit ( void )
{
2018-08-10 01:00:17 +02:00
int i ;
2015-06-21 17:33:46 +02:00
/* Make sure we're not getting called in the middle of updating joysticks */
SDL_assert ( ! SDL_updating_joystick ) ;
2017-10-10 20:10:15 +02:00
SDL_LockJoysticks ( ) ;
2016-11-29 14:04:42 +01:00
2015-06-21 17:33:46 +02:00
/* Stop the event polling */
while ( SDL_joysticks ) {
SDL_joysticks - > ref_count = 1 ;
SDL_JoystickClose ( SDL_joysticks ) ;
}
/* Quit the joystick setup */
2018-08-10 01:00:17 +02:00
for ( i = 0 ; i < SDL_arraysize ( SDL_joystick_drivers ) ; + + i ) {
SDL_joystick_drivers [ i ] - > Quit ( ) ;
}
2015-06-21 17:33:46 +02:00
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2016-11-29 14:04:42 +01:00
2015-06-21 17:33:46 +02:00
# if !SDL_EVENTS_DISABLED
SDL_QuitSubSystem ( SDL_INIT_EVENTS ) ;
# endif
2016-11-29 14:04:42 +01:00
2017-08-09 20:59:29 +02:00
SDL_DelHintCallback ( SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS ,
SDL_JoystickAllowBackgroundEventsChanged , NULL ) ;
2016-11-29 14:04:42 +01:00
if ( SDL_joystick_lock ) {
SDL_DestroyMutex ( SDL_joystick_lock ) ;
SDL_joystick_lock = NULL ;
}
2017-08-09 20:59:29 +02:00
SDL_GameControllerQuitMappings ( ) ;
2015-06-21 17:33:46 +02:00
}
static SDL_bool
SDL_PrivateJoystickShouldIgnoreEvent ( )
{
if ( SDL_joystick_allows_background_events ) {
return SDL_FALSE ;
}
2017-08-13 02:41:59 +02:00
if ( SDL_HasWindows ( ) & & SDL_GetKeyboardFocus ( ) = = NULL ) {
/* We have windows but we don't have focus, ignore the event. */
return SDL_TRUE ;
2015-06-21 17:33:46 +02:00
}
return SDL_FALSE ;
}
/* These are global for SDL_sysjoystick.c and SDL_events.c */
2018-08-10 01:00:17 +02:00
void SDL_PrivateJoystickAdded ( SDL_JoystickID device_instance )
2016-08-26 21:18:08 +02:00
{
# if !SDL_EVENTS_DISABLED
SDL_Event event ;
2018-08-10 01:00:17 +02:00
int device_index ;
device_index = SDL_JoystickGetDeviceIndexFromInstanceID ( device_instance ) ;
if ( device_index < 0 ) {
return ;
}
2016-08-26 21:18:08 +02:00
event . type = SDL_JOYDEVICEADDED ;
if ( SDL_GetEventState ( event . type ) = = SDL_ENABLE ) {
event . jdevice . which = device_index ;
2017-10-11 02:41:41 +02:00
SDL_PushEvent ( & event ) ;
2016-08-26 21:18:08 +02:00
}
# endif /* !SDL_EVENTS_DISABLED */
}
/*
* If there is an existing add event in the queue , it needs to be modified
* to have the right value for which , because the number of controllers in
* the system is now one less .
*/
static void UpdateEventsForDeviceRemoval ( )
{
int i , num_events ;
SDL_Event * events ;
2018-10-23 02:50:32 +02:00
SDL_bool isstack ;
2016-08-26 21:18:08 +02:00
num_events = SDL_PeepEvents ( NULL , 0 , SDL_PEEKEVENT , SDL_JOYDEVICEADDED , SDL_JOYDEVICEADDED ) ;
if ( num_events < = 0 ) {
return ;
}
2018-10-23 02:50:32 +02:00
events = SDL_small_alloc ( SDL_Event , num_events , & isstack ) ;
2016-08-26 21:18:08 +02:00
if ( ! events ) {
return ;
}
num_events = SDL_PeepEvents ( events , num_events , SDL_GETEVENT , SDL_JOYDEVICEADDED , SDL_JOYDEVICEADDED ) ;
for ( i = 0 ; i < num_events ; + + i ) {
- - events [ i ] . jdevice . which ;
}
SDL_PeepEvents ( events , num_events , SDL_ADDEVENT , 0 , 0 ) ;
2018-10-23 02:50:32 +02:00
SDL_small_free ( events , isstack ) ;
2016-08-26 21:18:08 +02:00
}
void SDL_PrivateJoystickRemoved ( SDL_JoystickID device_instance )
{
2018-08-10 01:03:50 +02:00
SDL_Joystick * joystick ;
2016-08-26 21:18:08 +02:00
# if !SDL_EVENTS_DISABLED
SDL_Event event ;
event . type = SDL_JOYDEVICEREMOVED ;
if ( SDL_GetEventState ( event . type ) = = SDL_ENABLE ) {
event . jdevice . which = device_instance ;
2017-10-11 02:41:41 +02:00
SDL_PushEvent ( & event ) ;
2016-08-26 21:18:08 +02:00
}
UpdateEventsForDeviceRemoval ( ) ;
# endif /* !SDL_EVENTS_DISABLED */
2018-08-10 01:03:50 +02:00
/* Mark this joystick as no longer attached */
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
if ( joystick - > instance_id = = device_instance ) {
joystick - > attached = SDL_FALSE ;
joystick - > force_recentering = SDL_TRUE ;
break ;
}
}
2016-08-26 21:18:08 +02:00
}
2015-06-21 17:33:46 +02:00
int
SDL_PrivateJoystickAxis ( SDL_Joystick * joystick , Uint8 axis , Sint16 value )
{
int posted ;
/* Make sure we're not getting garbage or duplicate events */
if ( axis > = joystick - > naxes ) {
return 0 ;
}
2017-01-04 08:39:28 +01:00
if ( ! joystick - > axes [ axis ] . has_initial_value ) {
2017-01-04 19:28:07 +01:00
joystick - > axes [ axis ] . initial_value = value ;
2017-01-04 08:39:28 +01:00
joystick - > axes [ axis ] . value = value ;
joystick - > axes [ axis ] . zero = value ;
joystick - > axes [ axis ] . has_initial_value = SDL_TRUE ;
}
2017-09-22 17:56:09 +02:00
if ( value = = joystick - > axes [ axis ] . value ) {
return 0 ;
}
2017-01-04 08:39:28 +01:00
if ( ! joystick - > axes [ axis ] . sent_initial_value ) {
2017-09-21 19:29:17 +02:00
/* Make sure we don't send motion until there's real activity on this axis */
const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80 ; /* ShanWan PS3 controller needed 96 */
if ( SDL_abs ( value - joystick - > axes [ axis ] . value ) < = MAX_ALLOWED_JITTER ) {
return 0 ;
}
2017-01-04 08:39:28 +01:00
joystick - > axes [ axis ] . sent_initial_value = SDL_TRUE ;
joystick - > axes [ axis ] . value = value ; /* Just so we pass the check above */
2017-01-04 19:28:07 +01:00
SDL_PrivateJoystickAxis ( joystick , axis , joystick - > axes [ axis ] . initial_value ) ;
2016-12-23 02:33:45 +01:00
}
2015-06-21 17:33:46 +02:00
/* We ignore events if we don't have keyboard focus, except for centering
* events .
*/
if ( SDL_PrivateJoystickShouldIgnoreEvent ( ) ) {
2016-12-23 02:33:45 +01:00
if ( ( value > joystick - > axes [ axis ] . zero & & value > = joystick - > axes [ axis ] . value ) | |
( value < joystick - > axes [ axis ] . zero & & value < = joystick - > axes [ axis ] . value ) ) {
2015-06-21 17:33:46 +02:00
return 0 ;
}
}
/* Update internal joystick state */
2016-12-23 02:33:45 +01:00
joystick - > axes [ axis ] . value = value ;
2015-06-21 17:33:46 +02:00
/* Post the event, if desired */
posted = 0 ;
# if !SDL_EVENTS_DISABLED
if ( SDL_GetEventState ( SDL_JOYAXISMOTION ) = = SDL_ENABLE ) {
SDL_Event event ;
event . type = SDL_JOYAXISMOTION ;
event . jaxis . which = joystick - > instance_id ;
event . jaxis . axis = axis ;
event . jaxis . value = value ;
posted = SDL_PushEvent ( & event ) = = 1 ;
}
# endif /* !SDL_EVENTS_DISABLED */
2018-08-10 01:00:17 +02:00
return posted ;
2015-06-21 17:33:46 +02:00
}
int
SDL_PrivateJoystickHat ( SDL_Joystick * joystick , Uint8 hat , Uint8 value )
{
int posted ;
/* Make sure we're not getting garbage or duplicate events */
if ( hat > = joystick - > nhats ) {
return 0 ;
}
if ( value = = joystick - > hats [ hat ] ) {
return 0 ;
}
/* We ignore events if we don't have keyboard focus, except for centering
* events .
*/
if ( SDL_PrivateJoystickShouldIgnoreEvent ( ) ) {
if ( value ! = SDL_HAT_CENTERED ) {
return 0 ;
}
}
/* Update internal joystick state */
joystick - > hats [ hat ] = value ;
/* Post the event, if desired */
posted = 0 ;
# if !SDL_EVENTS_DISABLED
if ( SDL_GetEventState ( SDL_JOYHATMOTION ) = = SDL_ENABLE ) {
SDL_Event event ;
event . jhat . type = SDL_JOYHATMOTION ;
event . jhat . which = joystick - > instance_id ;
event . jhat . hat = hat ;
event . jhat . value = value ;
posted = SDL_PushEvent ( & event ) = = 1 ;
}
# endif /* !SDL_EVENTS_DISABLED */
2018-08-10 01:00:17 +02:00
return posted ;
2015-06-21 17:33:46 +02:00
}
int
SDL_PrivateJoystickBall ( SDL_Joystick * joystick , Uint8 ball ,
Sint16 xrel , Sint16 yrel )
{
int posted ;
/* Make sure we're not getting garbage events */
if ( ball > = joystick - > nballs ) {
return 0 ;
}
/* We ignore events if we don't have keyboard focus. */
if ( SDL_PrivateJoystickShouldIgnoreEvent ( ) ) {
return 0 ;
}
/* Update internal mouse state */
joystick - > balls [ ball ] . dx + = xrel ;
joystick - > balls [ ball ] . dy + = yrel ;
/* Post the event, if desired */
posted = 0 ;
# if !SDL_EVENTS_DISABLED
if ( SDL_GetEventState ( SDL_JOYBALLMOTION ) = = SDL_ENABLE ) {
SDL_Event event ;
event . jball . type = SDL_JOYBALLMOTION ;
event . jball . which = joystick - > instance_id ;
event . jball . ball = ball ;
event . jball . xrel = xrel ;
event . jball . yrel = yrel ;
posted = SDL_PushEvent ( & event ) = = 1 ;
}
# endif /* !SDL_EVENTS_DISABLED */
2018-08-10 01:00:17 +02:00
return posted ;
2015-06-21 17:33:46 +02:00
}
int
SDL_PrivateJoystickButton ( SDL_Joystick * joystick , Uint8 button , Uint8 state )
{
int posted ;
# if !SDL_EVENTS_DISABLED
SDL_Event event ;
switch ( state ) {
case SDL_PRESSED :
event . type = SDL_JOYBUTTONDOWN ;
break ;
case SDL_RELEASED :
event . type = SDL_JOYBUTTONUP ;
break ;
default :
/* Invalid state -- bail */
2018-08-10 01:00:17 +02:00
return 0 ;
2015-06-21 17:33:46 +02:00
}
# endif /* !SDL_EVENTS_DISABLED */
/* Make sure we're not getting garbage or duplicate events */
if ( button > = joystick - > nbuttons ) {
return 0 ;
2015-10-01 00:39:30 +02:00
}
if ( state = = joystick - > buttons [ button ] ) {
return 0 ;
}
2015-06-21 17:33:46 +02:00
/* We ignore events if we don't have keyboard focus, except for button
* release . */
if ( SDL_PrivateJoystickShouldIgnoreEvent ( ) ) {
if ( state = = SDL_PRESSED ) {
return 0 ;
}
}
/* Update internal joystick state */
joystick - > buttons [ button ] = state ;
/* Post the event, if desired */
posted = 0 ;
# if !SDL_EVENTS_DISABLED
if ( SDL_GetEventState ( event . type ) = = SDL_ENABLE ) {
event . jbutton . which = joystick - > instance_id ;
event . jbutton . button = button ;
event . jbutton . state = state ;
posted = SDL_PushEvent ( & event ) = = 1 ;
}
# endif /* !SDL_EVENTS_DISABLED */
2018-08-10 01:00:17 +02:00
return posted ;
2015-06-21 17:33:46 +02:00
}
void
SDL_JoystickUpdate ( void )
{
2018-08-10 01:00:17 +02:00
int i ;
2016-12-14 15:25:09 +01:00
SDL_Joystick * joystick ;
2016-11-29 14:04:42 +01:00
2017-10-10 20:10:15 +02:00
SDL_LockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
2016-12-08 19:13:45 +01:00
if ( SDL_updating_joystick ) {
/* The joysticks are already being updated */
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2016-12-08 19:13:45 +01:00
return ;
}
2016-12-14 15:25:09 +01:00
SDL_updating_joystick = SDL_TRUE ;
2015-06-21 17:33:46 +02:00
2016-12-14 15:25:09 +01:00
/* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2016-12-08 19:13:45 +01:00
2016-12-14 15:25:09 +01:00
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
2018-08-10 01:03:50 +02:00
if ( joystick - > attached ) {
joystick - > driver - > Update ( joystick ) ;
2015-06-21 17:33:46 +02:00
2018-08-10 01:03:50 +02:00
if ( joystick - > delayed_guide_button ) {
SDL_GameControllerHandleDelayedGuideButton ( joystick ) ;
}
2018-03-19 22:42:51 +01:00
}
2015-06-21 17:33:46 +02:00
if ( joystick - > force_recentering ) {
2017-01-04 08:39:28 +01:00
/* Tell the app that everything is centered/unpressed... */
2015-09-21 04:08:36 +02:00
for ( i = 0 ; i < joystick - > naxes ; i + + ) {
2017-01-04 08:39:28 +01:00
if ( joystick - > axes [ i ] . has_initial_value ) {
SDL_PrivateJoystickAxis ( joystick , i , joystick - > axes [ i ] . zero ) ;
}
2015-09-21 04:08:36 +02:00
}
2015-06-21 17:33:46 +02:00
2015-09-21 04:08:36 +02:00
for ( i = 0 ; i < joystick - > nbuttons ; i + + ) {
2015-06-21 17:33:46 +02:00
SDL_PrivateJoystickButton ( joystick , i , 0 ) ;
2015-09-21 04:08:36 +02:00
}
2015-06-21 17:33:46 +02:00
2015-09-21 04:08:36 +02:00
for ( i = 0 ; i < joystick - > nhats ; i + + ) {
2015-06-21 17:33:46 +02:00
SDL_PrivateJoystickHat ( joystick , i , SDL_HAT_CENTERED ) ;
2015-09-21 04:08:36 +02:00
}
2015-06-21 17:33:46 +02:00
joystick - > force_recentering = SDL_FALSE ;
}
2016-12-14 15:25:09 +01:00
}
2015-06-21 17:33:46 +02:00
2017-10-10 20:10:15 +02:00
SDL_LockJoysticks ( ) ;
2016-12-08 19:13:45 +01:00
2016-12-14 15:25:09 +01:00
SDL_updating_joystick = SDL_FALSE ;
2015-06-21 17:33:46 +02:00
2016-12-14 15:25:09 +01:00
/* If any joysticks were closed while updating, free them here */
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
2015-06-21 17:33:46 +02:00
if ( joystick - > ref_count < = 0 ) {
SDL_JoystickClose ( joystick ) ;
}
}
/* this needs to happen AFTER walking the joystick list above, so that any
dangling hardware data from removed devices can be free ' d
*/
2018-08-10 01:00:17 +02:00
for ( i = 0 ; i < SDL_arraysize ( SDL_joystick_drivers ) ; + + i ) {
SDL_joystick_drivers [ i ] - > Detect ( ) ;
}
2016-11-29 14:04:42 +01:00
2017-10-10 20:10:15 +02:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 17:33:46 +02:00
}
int
SDL_JoystickEventState ( int state )
{
# if SDL_EVENTS_DISABLED
return SDL_DISABLE ;
# else
const Uint32 event_list [ ] = {
SDL_JOYAXISMOTION , SDL_JOYBALLMOTION , SDL_JOYHATMOTION ,
SDL_JOYBUTTONDOWN , SDL_JOYBUTTONUP , SDL_JOYDEVICEADDED , SDL_JOYDEVICEREMOVED
} ;
unsigned int i ;
switch ( state ) {
case SDL_QUERY :
state = SDL_DISABLE ;
for ( i = 0 ; i < SDL_arraysize ( event_list ) ; + + i ) {
state = SDL_EventState ( event_list [ i ] , SDL_QUERY ) ;
if ( state = = SDL_ENABLE ) {
break ;
}
}
break ;
default :
for ( i = 0 ; i < SDL_arraysize ( event_list ) ; + + i ) {
SDL_EventState ( event_list [ i ] , state ) ;
}
break ;
}
2018-08-10 01:00:17 +02:00
return state ;
2015-06-21 17:33:46 +02:00
# endif /* SDL_EVENTS_DISABLED */
}
2017-08-09 20:59:29 +02:00
void SDL_GetJoystickGUIDInfo ( SDL_JoystickGUID guid , Uint16 * vendor , Uint16 * product , Uint16 * version )
2016-11-11 02:19:34 +01:00
{
Uint16 * guid16 = ( Uint16 * ) guid . data ;
/* If the GUID fits the form of BUS 0000 VENDOR 0000 PRODUCT 0000, return the data */
if ( /* guid16[0] is device bus type */
2016-11-24 20:53:23 +01:00
guid16 [ 1 ] = = 0x0000 & &
2016-11-11 02:19:34 +01:00
/* guid16[2] is vendor ID */
2016-11-24 20:53:23 +01:00
guid16 [ 3 ] = = 0x0000 & &
2016-11-11 02:19:34 +01:00
/* guid16[4] is product ID */
2016-11-24 20:53:23 +01:00
guid16 [ 5 ] = = 0x0000
2016-11-11 02:19:34 +01:00
/* guid16[6] is product version */
2018-08-10 01:00:17 +02:00
) {
2016-11-11 02:19:34 +01:00
if ( vendor ) {
* vendor = guid16 [ 2 ] ;
}
if ( product ) {
* product = guid16 [ 4 ] ;
}
if ( version ) {
* version = guid16 [ 6 ] ;
}
} else {
if ( vendor ) {
* vendor = 0 ;
}
if ( product ) {
* product = 0 ;
}
if ( version ) {
* version = 0 ;
}
}
}
2018-08-10 01:00:17 +02:00
SDL_bool
SDL_IsJoystickPS4 ( Uint16 vendor , Uint16 product )
{
return ( GuessControllerType ( vendor , product ) = = k_eControllerType_PS4Controller ) ;
}
SDL_bool
SDL_IsJoystickNintendoSwitchPro ( Uint16 vendor , Uint16 product )
{
return ( GuessControllerType ( vendor , product ) = = k_eControllerType_SwitchProController ) ;
}
SDL_bool
SDL_IsJoystickSteamController ( Uint16 vendor , Uint16 product )
{
2018-09-28 16:01:24 +02:00
return BIsSteamController ( GuessControllerType ( vendor , product ) ) ;
2018-08-10 01:00:17 +02:00
}
SDL_bool
SDL_IsJoystickXbox360 ( Uint16 vendor , Uint16 product )
{
2018-09-24 20:49:25 +02:00
/* Filter out some bogus values here */
if ( vendor = = 0x0000 & & product = = 0x0000 ) {
return SDL_FALSE ;
}
if ( vendor = = 0x0001 & & product = = 0x0001 ) {
return SDL_FALSE ;
}
2018-08-10 01:00:17 +02:00
return ( GuessControllerType ( vendor , product ) = = k_eControllerType_XBox360Controller ) ;
}
SDL_bool
SDL_IsJoystickXboxOne ( Uint16 vendor , Uint16 product )
{
return ( GuessControllerType ( vendor , product ) = = k_eControllerType_XBoxOneController ) ;
}
2018-09-17 20:35:22 +02:00
SDL_bool
SDL_IsJoystickXInput ( SDL_JoystickGUID guid )
{
return ( guid . data [ 14 ] = = ' x ' ) ? SDL_TRUE : SDL_FALSE ;
}
SDL_bool
SDL_IsJoystickHIDAPI ( SDL_JoystickGUID guid )
{
return ( guid . data [ 14 ] = = ' h ' ) ? SDL_TRUE : SDL_FALSE ;
}
2017-01-31 21:23:29 +01:00
static SDL_bool SDL_IsJoystickProductWheel ( Uint32 vidpid )
2017-01-27 14:59:58 +01:00
{
static Uint32 wheel_joysticks [ ] = {
MAKE_VIDPID ( 0x046d , 0xc294 ) , /* Logitech generic wheel */
MAKE_VIDPID ( 0x046d , 0xc295 ) , /* Logitech Momo Force */
MAKE_VIDPID ( 0x046d , 0xc298 ) , /* Logitech Driving Force Pro */
MAKE_VIDPID ( 0x046d , 0xc299 ) , /* Logitech G25 */
MAKE_VIDPID ( 0x046d , 0xc29a ) , /* Logitech Driving Force GT */
MAKE_VIDPID ( 0x046d , 0xc29b ) , /* Logitech G27 */
MAKE_VIDPID ( 0x046d , 0xc261 ) , /* Logitech G920 (initial mode) */
MAKE_VIDPID ( 0x046d , 0xc262 ) , /* Logitech G920 (active mode) */
MAKE_VIDPID ( 0x044f , 0xb65d ) , /* Thrustmaster Wheel FFB */
2017-01-27 15:05:50 +01:00
MAKE_VIDPID ( 0x044f , 0xb66d ) , /* Thrustmaster Wheel FFB */
2017-01-27 14:59:58 +01:00
MAKE_VIDPID ( 0x044f , 0xb677 ) , /* Thrustmaster T150 */
MAKE_VIDPID ( 0x044f , 0xb664 ) , /* Thrustmaster TX (initial mode) */
MAKE_VIDPID ( 0x044f , 0xb669 ) , /* Thrustmaster TX (active mode) */
} ;
int i ;
for ( i = 0 ; i < SDL_arraysize ( wheel_joysticks ) ; + + i ) {
2017-01-31 19:20:09 +01:00
if ( vidpid = = wheel_joysticks [ i ] ) {
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2017-01-31 21:23:29 +01:00
static SDL_bool SDL_IsJoystickProductFlightStick ( Uint32 vidpid )
2017-01-31 19:20:09 +01:00
{
static Uint32 flightstick_joysticks [ ] = {
2017-01-31 21:30:55 +01:00
MAKE_VIDPID ( 0x044f , 0x0402 ) , /* HOTAS Warthog Joystick */
MAKE_VIDPID ( 0x0738 , 0x2221 ) , /* Saitek Pro Flight X-56 Rhino Stick */
2017-01-31 19:20:09 +01:00
} ;
int i ;
for ( i = 0 ; i < SDL_arraysize ( flightstick_joysticks ) ; + + i ) {
if ( vidpid = = flightstick_joysticks [ i ] ) {
2017-01-27 14:59:58 +01:00
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2017-01-31 21:23:29 +01:00
static SDL_bool SDL_IsJoystickProductThrottle ( Uint32 vidpid )
{
static Uint32 throttle_joysticks [ ] = {
2017-01-31 21:30:55 +01:00
MAKE_VIDPID ( 0x044f , 0x0404 ) , /* HOTAS Warthog Throttle */
MAKE_VIDPID ( 0x0738 , 0xa221 ) , /* Saitek Pro Flight X-56 Rhino Throttle */
2017-01-31 21:23:29 +01:00
} ;
int i ;
for ( i = 0 ; i < SDL_arraysize ( throttle_joysticks ) ; + + i ) {
if ( vidpid = = throttle_joysticks [ i ] ) {
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2017-01-27 14:59:58 +01:00
static SDL_JoystickType SDL_GetJoystickGUIDType ( SDL_JoystickGUID guid )
{
2017-01-31 19:20:09 +01:00
Uint16 vendor ;
Uint16 product ;
Uint32 vidpid ;
2018-09-17 20:35:22 +02:00
if ( SDL_IsJoystickXInput ( guid ) ) {
2017-01-27 14:59:58 +01:00
/* XInput GUID, get the type based on the XInput device subtype */
switch ( guid . data [ 15 ] ) {
case 0x01 : /* XINPUT_DEVSUBTYPE_GAMEPAD */
return SDL_JOYSTICK_TYPE_GAMECONTROLLER ;
case 0x02 : /* XINPUT_DEVSUBTYPE_WHEEL */
return SDL_JOYSTICK_TYPE_WHEEL ;
case 0x03 : /* XINPUT_DEVSUBTYPE_ARCADE_STICK */
return SDL_JOYSTICK_TYPE_ARCADE_STICK ;
case 0x04 : /* XINPUT_DEVSUBTYPE_FLIGHT_STICK */
return SDL_JOYSTICK_TYPE_FLIGHT_STICK ;
case 0x05 : /* XINPUT_DEVSUBTYPE_DANCE_PAD */
return SDL_JOYSTICK_TYPE_DANCE_PAD ;
case 0x06 : /* XINPUT_DEVSUBTYPE_GUITAR */
case 0x07 : /* XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE */
case 0x0B : /* XINPUT_DEVSUBTYPE_GUITAR_BASS */
return SDL_JOYSTICK_TYPE_GUITAR ;
case 0x08 : /* XINPUT_DEVSUBTYPE_DRUM_KIT */
return SDL_JOYSTICK_TYPE_DRUM_KIT ;
case 0x13 : /* XINPUT_DEVSUBTYPE_ARCADE_PAD */
return SDL_JOYSTICK_TYPE_ARCADE_PAD ;
default :
return SDL_JOYSTICK_TYPE_UNKNOWN ;
}
}
2017-01-31 19:20:09 +01:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , & product , NULL ) ;
vidpid = MAKE_VIDPID ( vendor , product ) ;
2017-01-31 21:23:29 +01:00
if ( SDL_IsJoystickProductWheel ( vidpid ) ) {
2017-01-27 14:59:58 +01:00
return SDL_JOYSTICK_TYPE_WHEEL ;
}
2017-01-31 21:23:29 +01:00
if ( SDL_IsJoystickProductFlightStick ( vidpid ) ) {
2017-01-31 19:20:09 +01:00
return SDL_JOYSTICK_TYPE_FLIGHT_STICK ;
}
2017-01-31 21:23:29 +01:00
if ( SDL_IsJoystickProductThrottle ( vidpid ) ) {
return SDL_JOYSTICK_TYPE_THROTTLE ;
}
2018-08-10 01:00:17 +02:00
if ( GuessControllerType ( vendor , product ) ! = k_eControllerType_UnknownNonSteamController ) {
return SDL_JOYSTICK_TYPE_GAMECONTROLLER ;
}
2017-01-27 14:59:58 +01:00
return SDL_JOYSTICK_TYPE_UNKNOWN ;
}
2018-08-10 01:00:17 +02:00
static SDL_bool SDL_IsPS4RemapperRunning ( void )
{
# ifdef __WIN32__
const char * mapper_processes [ ] = {
" DS4Windows.exe " ,
" InputMapper.exe " ,
} ;
int i ;
PROCESSENTRY32 pe32 ;
SDL_bool found = SDL_FALSE ;
/* Take a snapshot of all processes in the system */
HANDLE hProcessSnap = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS , 0 ) ;
if ( hProcessSnap ! = INVALID_HANDLE_VALUE ) {
pe32 . dwSize = sizeof ( PROCESSENTRY32 ) ;
if ( Process32First ( hProcessSnap , & pe32 ) ) {
do
{
for ( i = 0 ; i < SDL_arraysize ( mapper_processes ) ; + + i ) {
if ( SDL_strcasecmp ( pe32 . szExeFile , mapper_processes [ i ] ) = = 0 ) {
found = SDL_TRUE ;
}
}
} while ( Process32Next ( hProcessSnap , & pe32 ) & & ! found ) ;
}
CloseHandle ( hProcessSnap ) ;
}
return found ;
# else
return SDL_FALSE ;
# endif
}
SDL_bool SDL_ShouldIgnoreJoystick ( const char * name , SDL_JoystickGUID guid )
{
Uint16 vendor ;
Uint16 product ;
SDL_GetJoystickGUIDInfo ( guid , & vendor , & product , NULL ) ;
if ( SDL_IsJoystickPS4 ( vendor , product ) & & SDL_IsPS4RemapperRunning ( ) ) {
return SDL_TRUE ;
}
if ( SDL_IsGameControllerNameAndGUID ( name , guid ) & &
SDL_ShouldIgnoreGameController ( name , guid ) ) {
return SDL_TRUE ;
}
return SDL_FALSE ;
}
2015-06-21 17:33:46 +02:00
/* return the guid for this index */
SDL_JoystickGUID SDL_JoystickGetDeviceGUID ( int device_index )
{
2018-08-10 01:00:17 +02:00
SDL_JoystickDriver * driver ;
SDL_JoystickGUID guid ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
guid = driver - > GetDeviceGUID ( device_index ) ;
} else {
SDL_zero ( guid ) ;
2015-06-21 17:33:46 +02:00
}
2018-08-10 01:00:17 +02:00
SDL_UnlockJoysticks ( ) ;
return guid ;
2015-06-21 17:33:46 +02:00
}
2016-11-11 02:19:34 +01:00
Uint16 SDL_JoystickGetDeviceVendor ( int device_index )
{
Uint16 vendor ;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID ( device_index ) ;
2017-01-27 14:59:58 +01:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , NULL , NULL ) ;
2016-11-11 02:19:34 +01:00
return vendor ;
}
Uint16 SDL_JoystickGetDeviceProduct ( int device_index )
{
Uint16 product ;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID ( device_index ) ;
2017-01-27 14:59:58 +01:00
SDL_GetJoystickGUIDInfo ( guid , NULL , & product , NULL ) ;
2016-11-11 02:19:34 +01:00
return product ;
}
Uint16 SDL_JoystickGetDeviceProductVersion ( int device_index )
{
Uint16 version ;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID ( device_index ) ;
2017-01-27 14:59:58 +01:00
SDL_GetJoystickGUIDInfo ( guid , NULL , NULL , & version ) ;
2016-11-11 02:19:34 +01:00
return version ;
}
2017-01-27 14:59:58 +01:00
SDL_JoystickType SDL_JoystickGetDeviceType ( int device_index )
{
SDL_JoystickType type ;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID ( device_index ) ;
type = SDL_GetJoystickGUIDType ( guid ) ;
if ( type = = SDL_JOYSTICK_TYPE_UNKNOWN ) {
if ( SDL_IsGameController ( device_index ) ) {
type = SDL_JOYSTICK_TYPE_GAMECONTROLLER ;
}
}
return type ;
}
2017-03-10 01:09:16 +01:00
SDL_JoystickID SDL_JoystickGetDeviceInstanceID ( int device_index )
{
2018-08-10 01:00:17 +02:00
SDL_JoystickDriver * driver ;
SDL_JoystickID instance_id = - 1 ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
instance_id = driver - > GetDeviceInstanceID ( device_index ) ;
}
SDL_UnlockJoysticks ( ) ;
return instance_id ;
}
int SDL_JoystickGetDeviceIndexFromInstanceID ( SDL_JoystickID instance_id )
{
int i , num_joysticks , device_index = - 1 ;
SDL_LockJoysticks ( ) ;
num_joysticks = SDL_NumJoysticks ( ) ;
for ( i = 0 ; i < num_joysticks ; + + i ) {
if ( SDL_JoystickGetDeviceInstanceID ( i ) = = instance_id ) {
device_index = i ;
break ;
}
2017-03-10 01:09:16 +01:00
}
2018-08-10 01:00:17 +02:00
SDL_UnlockJoysticks ( ) ;
return device_index ;
2017-03-10 01:09:16 +01:00
}
2015-06-21 17:33:46 +02:00
SDL_JoystickGUID SDL_JoystickGetGUID ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
SDL_JoystickGUID emptyGUID ;
SDL_zero ( emptyGUID ) ;
return emptyGUID ;
}
2018-08-10 01:00:17 +02:00
return joystick - > guid ;
2015-06-21 17:33:46 +02:00
}
2016-11-11 02:19:34 +01:00
Uint16 SDL_JoystickGetVendor ( SDL_Joystick * joystick )
{
Uint16 vendor ;
SDL_JoystickGUID guid = SDL_JoystickGetGUID ( joystick ) ;
2017-01-27 14:59:58 +01:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , NULL , NULL ) ;
2016-11-11 02:19:34 +01:00
return vendor ;
}
Uint16 SDL_JoystickGetProduct ( SDL_Joystick * joystick )
{
Uint16 product ;
SDL_JoystickGUID guid = SDL_JoystickGetGUID ( joystick ) ;
2017-01-27 14:59:58 +01:00
SDL_GetJoystickGUIDInfo ( guid , NULL , & product , NULL ) ;
2016-11-11 02:19:34 +01:00
return product ;
}
Uint16 SDL_JoystickGetProductVersion ( SDL_Joystick * joystick )
{
Uint16 version ;
SDL_JoystickGUID guid = SDL_JoystickGetGUID ( joystick ) ;
2017-01-27 14:59:58 +01:00
SDL_GetJoystickGUIDInfo ( guid , NULL , NULL , & version ) ;
2016-11-11 02:19:34 +01:00
return version ;
}
2017-01-27 14:59:58 +01:00
SDL_JoystickType SDL_JoystickGetType ( SDL_Joystick * joystick )
{
SDL_JoystickType type ;
SDL_JoystickGUID guid = SDL_JoystickGetGUID ( joystick ) ;
type = SDL_GetJoystickGUIDType ( guid ) ;
if ( type = = SDL_JOYSTICK_TYPE_UNKNOWN ) {
if ( joystick & & joystick - > is_game_controller ) {
type = SDL_JOYSTICK_TYPE_GAMECONTROLLER ;
}
}
return type ;
}
2015-06-21 17:33:46 +02:00
/* convert the guid to a printable string */
void SDL_JoystickGetGUIDString ( SDL_JoystickGUID guid , char * pszGUID , int cbGUID )
{
static const char k_rgchHexToASCII [ ] = " 0123456789abcdef " ;
int i ;
if ( ( pszGUID = = NULL ) | | ( cbGUID < = 0 ) ) {
return ;
}
for ( i = 0 ; i < sizeof ( guid . data ) & & i < ( cbGUID - 1 ) / 2 ; i + + ) {
/* each input byte writes 2 ascii chars, and might write a null byte. */
/* If we don't have room for next input byte, stop */
unsigned char c = guid . data [ i ] ;
* pszGUID + + = k_rgchHexToASCII [ c > > 4 ] ;
* pszGUID + + = k_rgchHexToASCII [ c & 0x0F ] ;
}
* pszGUID = ' \0 ' ;
}
/*-----------------------------------------------------------------------------
* Purpose : Returns the 4 bit nibble for a hex character
* Input : c -
* Output : unsigned char
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static unsigned char nibble ( char c )
{
if ( ( c > = ' 0 ' ) & & ( c < = ' 9 ' ) ) {
return ( unsigned char ) ( c - ' 0 ' ) ;
}
if ( ( c > = ' A ' ) & & ( c < = ' F ' ) ) {
return ( unsigned char ) ( c - ' A ' + 0x0a ) ;
}
if ( ( c > = ' a ' ) & & ( c < = ' f ' ) ) {
return ( unsigned char ) ( c - ' a ' + 0x0a ) ;
}
/* received an invalid character, and no real way to return an error */
/* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
return 0 ;
}
/* convert the string version of a joystick guid to the struct */
SDL_JoystickGUID SDL_JoystickGetGUIDFromString ( const char * pchGUID )
{
SDL_JoystickGUID guid ;
int maxoutputbytes = sizeof ( guid ) ;
size_t len = SDL_strlen ( pchGUID ) ;
Uint8 * p ;
size_t i ;
/* Make sure it's even */
len = ( len ) & ~ 0x1 ;
SDL_memset ( & guid , 0x00 , sizeof ( guid ) ) ;
p = ( Uint8 * ) & guid ;
for ( i = 0 ; ( i < len ) & & ( ( p - ( Uint8 * ) & guid ) < maxoutputbytes ) ; i + = 2 , p + + ) {
* p = ( nibble ( pchGUID [ i ] ) < < 4 ) | nibble ( pchGUID [ i + 1 ] ) ;
}
return guid ;
}
2015-10-01 00:39:30 +02:00
/* update the power level for this joystick */
void SDL_PrivateJoystickBatteryLevel ( SDL_Joystick * joystick , SDL_JoystickPowerLevel ePowerLevel )
{
joystick - > epowerlevel = ePowerLevel ;
}
/* return its power level */
SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-10 01:00:17 +02:00
return SDL_JOYSTICK_POWER_UNKNOWN ;
2015-10-01 00:39:30 +02:00
}
return joystick - > epowerlevel ;
}
2015-06-21 17:33:46 +02:00
/* vi: set ts=4 sw=4 expandtab: */