2015-06-21 15:33:46 +00:00
/*
Simple DirectMedia Layer
2020-01-17 04:49:25 +00:00
Copyright ( C ) 1997 - 2020 Sam Lantinga < slouken @ libsdl . org >
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
# include "SDL_atomic.h"
2015-06-21 15:33:46 +00:00
# include "SDL_events.h"
# include "SDL_sysjoystick.h"
# include "SDL_hints.h"
# if !SDL_EVENTS_DISABLED
# include "../events/SDL_events_c.h"
# endif
2017-08-13 00:41:59 +00:00
# include "../video/SDL_sysvideo.h"
2019-12-19 23:01:35 +00:00
# include "hidapi/SDL_hidapijoystick_c.h"
2015-06-21 15:33:46 +00:00
2018-08-09 23:00:17 +00:00
/* This is included in only one place because it has a large static list of controllers */
# include "controller_type.h"
2017-01-27 13:59:58 +00:00
2018-08-09 23:00:17 +00:00
# ifdef __WIN32__
/* Needed for checking for input remapping programs */
2018-08-09 23:03:29 +00:00
# include "../core/windows/SDL_windows.h"
2018-08-09 23:00:17 +00:00
# undef UNICODE /* We want ASCII functions */
# include <tlhelp32.h>
# endif
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
# if SDL_JOYSTICK_VIRTUAL
2020-03-15 19:05:36 +00:00
# include "./virtual/SDL_virtualjoystick_c.h"
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
# endif
2018-08-09 23:00:17 +00:00
static SDL_JoystickDriver * SDL_joystick_drivers [ ] = {
2020-03-16 19:23:38 +00:00
# ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
& SDL_HIDAPI_JoystickDriver ,
# endif
2020-11-24 02:24:05 +00:00
# ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
& SDL_RAWINPUT_JoystickDriver ,
# endif
2020-04-19 04:41:37 +00:00
# if defined(SDL_JOYSTICK_WGI)
& SDL_WGI_JoystickDriver ,
# endif
2018-08-09 23:00:17 +00:00
# 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
2020-11-24 04:57:14 +00:00
# if (defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__TVOS__)) && !defined(SDL_JOYSTICK_DISABLED)
2018-08-09 23:00:17 +00:00
& SDL_IOS_JoystickDriver ,
# endif
# ifdef SDL_JOYSTICK_ANDROID
& SDL_ANDROID_JoystickDriver ,
# endif
2018-08-10 18:32:30 +00:00
# ifdef SDL_JOYSTICK_EMSCRIPTEN
& SDL_EMSCRIPTEN_JoystickDriver ,
# endif
2018-08-10 19:04:08 +00:00
# ifdef SDL_JOYSTICK_HAIKU
& SDL_HAIKU_JoystickDriver ,
# endif
2018-08-10 18:42:40 +00: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
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
# ifdef SDL_JOYSTICK_VIRTUAL
& SDL_VIRTUAL_JoystickDriver ,
# endif
2018-08-09 23:00:17 +00:00
# if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
& SDL_DUMMY_JoystickDriver
# endif
} ;
2015-06-21 15:33:46 +00:00
static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE ;
static SDL_Joystick * SDL_joysticks = NULL ;
2016-12-14 14:25:09 +00:00
static SDL_bool SDL_updating_joystick = SDL_FALSE ;
2016-11-29 13:04:42 +00:00
static SDL_mutex * SDL_joystick_lock = NULL ; /* This needs to support recursive locks */
2018-08-09 23:00:17 +00:00
static SDL_atomic_t SDL_next_joystick_instance_id ;
2019-12-21 04:12:03 +00:00
static int SDL_joystick_player_count = 0 ;
static SDL_JoystickID * SDL_joystick_players = NULL ;
2016-11-29 13:04:42 +00:00
2016-12-08 18:13:45 +00:00
void
2017-10-10 18:10:15 +00:00
SDL_LockJoysticks ( void )
2016-11-29 13:04:42 +00:00
{
if ( SDL_joystick_lock ) {
SDL_LockMutex ( SDL_joystick_lock ) ;
}
}
2016-12-08 18:13:45 +00:00
void
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( void )
2016-11-29 13:04:42 +00:00
{
if ( SDL_joystick_lock ) {
SDL_UnlockMutex ( SDL_joystick_lock ) ;
}
}
2019-12-21 04:12:03 +00:00
static int
SDL_FindFreePlayerIndex ( )
{
int player_index ;
for ( player_index = 0 ; player_index < SDL_joystick_player_count ; + + player_index ) {
if ( SDL_joystick_players [ player_index ] = = - 1 ) {
return player_index ;
}
}
return player_index ;
}
static int
SDL_GetPlayerIndexForJoystickID ( SDL_JoystickID instance_id )
{
int player_index ;
for ( player_index = 0 ; player_index < SDL_joystick_player_count ; + + player_index ) {
if ( instance_id = = SDL_joystick_players [ player_index ] ) {
break ;
}
}
if ( player_index = = SDL_joystick_player_count ) {
player_index = - 1 ;
}
return player_index ;
}
static SDL_JoystickID
SDL_GetJoystickIDForPlayerIndex ( int player_index )
{
if ( player_index < 0 | | player_index > = SDL_joystick_player_count ) {
return - 1 ;
}
return SDL_joystick_players [ player_index ] ;
}
static SDL_bool
SDL_SetJoystickIDForPlayerIndex ( int player_index , SDL_JoystickID instance_id )
{
SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex ( player_index ) ;
SDL_JoystickDriver * driver ;
int device_index ;
2020-03-08 03:21:21 +00:00
int existing_player_index ;
2019-12-21 04:12:03 +00:00
if ( player_index < 0 ) {
return SDL_FALSE ;
}
if ( player_index > = SDL_joystick_player_count ) {
SDL_JoystickID * new_players = ( SDL_JoystickID * ) SDL_realloc ( SDL_joystick_players , ( player_index + 1 ) * sizeof ( * SDL_joystick_players ) ) ;
if ( ! new_players ) {
SDL_OutOfMemory ( ) ;
return SDL_FALSE ;
}
SDL_joystick_players = new_players ;
2020-01-13 23:35:54 +00:00
SDL_memset ( & SDL_joystick_players [ SDL_joystick_player_count ] , 0xFF , ( player_index - SDL_joystick_player_count + 1 ) * sizeof ( SDL_joystick_players [ 0 ] ) ) ;
SDL_joystick_player_count = player_index + 1 ;
2020-03-08 01:20:04 +00:00
} else if ( SDL_joystick_players [ player_index ] = = instance_id ) {
/* Joystick is already assigned the requested player index */
return SDL_TRUE ;
2019-12-21 04:12:03 +00:00
}
2020-03-08 03:21:21 +00:00
/* Clear the old player index */
existing_player_index = SDL_GetPlayerIndexForJoystickID ( instance_id ) ;
if ( existing_player_index > = 0 ) {
SDL_joystick_players [ existing_player_index ] = - 1 ;
}
2019-12-21 04:12:03 +00:00
SDL_joystick_players [ player_index ] = instance_id ;
/* Update the driver with the new index */
device_index = SDL_JoystickGetDeviceIndexFromInstanceID ( instance_id ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
driver - > SetDevicePlayerIndex ( device_index , player_index ) ;
}
/* Move any existing joystick to another slot */
if ( existing_instance > = 0 ) {
SDL_SetJoystickIDForPlayerIndex ( SDL_FindFreePlayerIndex ( ) , existing_instance ) ;
}
return SDL_TRUE ;
}
2015-06-21 15:33:46 +00:00
2017-08-14 13:28:21 +00:00
static void SDLCALL
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
int i , status ;
2015-06-21 15:33:46 +00:00
2017-08-09 18:59:29 +00:00
SDL_GameControllerInitMappings ( ) ;
2016-11-29 13:04:42 +00:00
/* Create the joystick list lock */
if ( ! SDL_joystick_lock ) {
SDL_joystick_lock = SDL_CreateMutex ( ) ;
}
2015-06-21 15:33:46 +00: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-09 23:00:17 +00: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 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
return status ;
2015-06-21 15:33:46 +00:00
}
/*
* Count the number of joysticks attached to the system
*/
int
SDL_NumJoysticks ( void )
{
2018-08-09 23:00:17 +00: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 15:33:46 +00:00
}
/*
* Get the implementation dependent name of a joystick
*/
const char *
SDL_JoystickNameForIndex ( int device_index )
{
2018-08-09 23:00:17 +00:00
SDL_JoystickDriver * driver ;
const char * name = NULL ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
2020-03-13 02:47:30 +00:00
name = driver - > GetDeviceName ( device_index ) ;
2015-06-21 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
SDL_UnlockJoysticks ( ) ;
/* FIXME: Really we should reference count this name so it doesn't go away after unlock */
return name ;
2015-06-21 15:33:46 +00:00
}
2019-12-21 04:12:03 +00:00
/*
* Get the player index of a joystick , or - 1 if it ' s not available
*/
2018-10-25 23:53:14 +00:00
int
SDL_JoystickGetDevicePlayerIndex ( int device_index )
{
2019-12-21 04:12:03 +00:00
int player_index ;
2018-10-25 23:53:14 +00:00
SDL_LockJoysticks ( ) ;
2019-12-21 04:12:03 +00:00
player_index = SDL_GetPlayerIndexForJoystickID ( SDL_JoystickGetDeviceInstanceID ( device_index ) ) ;
2018-10-25 23:53:14 +00:00
SDL_UnlockJoysticks ( ) ;
return player_index ;
}
2017-01-04 07:39:28 +00: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 13:59:58 +00:00
static Uint32 zero_centered_joysticks [ ] = {
MAKE_VIDPID ( 0x0e8f , 0x3013 ) , /* HuiJia SNES USB adapter */
MAKE_VIDPID ( 0x05a0 , 0x3232 ) , /* 8Bitdo Zero Gamepad */
2017-01-04 07:39:28 +00:00
} ;
int i ;
2017-01-27 13:59:58 +00:00
Uint32 id = MAKE_VIDPID ( SDL_JoystickGetVendor ( joystick ) ,
SDL_JoystickGetProduct ( joystick ) ) ;
2017-01-04 07:39:28 +00:00
2017-01-20 16:13:23 +00:00
/*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/
2017-01-04 15:06:48 +00:00
if ( joystick - > naxes = = 2 ) {
/* Assume D-pad or thumbstick style axes are centered at 0 */
return SDL_TRUE ;
}
2017-01-04 07:39:28 +00:00
for ( i = 0 ; i < SDL_arraysize ( zero_centered_joysticks ) ; + + i ) {
2017-01-27 13:59:58 +00:00
if ( id = = zero_centered_joysticks [ i ] ) {
2017-01-04 07:39:28 +00:00
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
SDL_JoystickDriver * driver ;
SDL_JoystickID instance_id ;
2015-06-21 15:33:46 +00:00
SDL_Joystick * joystick ;
SDL_Joystick * joysticklist ;
const char * joystickname = NULL ;
2017-10-10 18:10:15 +00:00
SDL_LockJoysticks ( ) ;
2016-11-29 13:04:42 +00:00
2018-08-09 23:00:17 +00:00
if ( ! SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
SDL_UnlockJoysticks ( ) ;
return NULL ;
}
2015-06-21 15:33:46 +00:00
joysticklist = SDL_joysticks ;
/* If the joystick is already open, return it
2017-03-10 00:09:16 +00:00
* it is important that we have a single joystick * for each instance id
*/
2018-08-09 23:00:17 +00:00
instance_id = driver - > GetDeviceInstanceID ( device_index ) ;
2015-06-21 15:33:46 +00:00
while ( joysticklist ) {
2018-08-09 23:00:17 +00:00
if ( instance_id = = joysticklist - > instance_id ) {
2015-06-21 15:33:46 +00:00
joystick = joysticklist ;
+ + joystick - > ref_count ;
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2018-08-09 23:00:17 +00:00
return joystick ;
2015-06-21 15:33:46 +00:00
}
joysticklist = joysticklist - > next ;
}
/* Create and initialize the joystick */
2017-01-27 13:59:58 +00:00
joystick = ( SDL_Joystick * ) SDL_calloc ( sizeof ( * joystick ) , 1 ) ;
2015-06-21 15:33:46 +00:00
if ( joystick = = NULL ) {
SDL_OutOfMemory ( ) ;
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 15:33:46 +00:00
return NULL ;
}
2018-08-09 23:00:17 +00:00
joystick - > driver = driver ;
joystick - > instance_id = instance_id ;
2018-08-09 23:03:50 +00:00
joystick - > attached = SDL_TRUE ;
2019-06-19 13:43:04 +00:00
joystick - > epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN ;
2015-06-21 15:33:46 +00:00
2018-08-09 23:00:17 +00:00
if ( driver - > Open ( joystick , device_index ) < 0 ) {
2015-06-21 15:33:46 +00:00
SDL_free ( joystick ) ;
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 15:33:46 +00:00
return NULL ;
}
2018-08-09 23:00:17 +00:00
joystickname = driver - > GetDeviceName ( device_index ) ;
if ( joystickname ) {
2015-06-21 15:33:46 +00:00
joystick - > name = SDL_strdup ( joystickname ) ;
2018-08-09 23:00:17 +00:00
} else {
2015-06-21 15:33:46 +00:00
joystick - > name = NULL ;
2018-08-09 23:00:17 +00:00
}
joystick - > guid = driver - > GetDeviceGUID ( device_index ) ;
2015-06-21 15:33:46 +00:00
if ( joystick - > naxes > 0 ) {
2016-12-23 01:33:45 +00:00
joystick - > axes = ( SDL_JoystickAxisInfo * ) SDL_calloc ( joystick - > naxes , sizeof ( SDL_JoystickAxisInfo ) ) ;
2015-06-21 15:33:46 +00:00
}
if ( joystick - > nhats > 0 ) {
2016-12-23 01:33:45 +00:00
joystick - > hats = ( Uint8 * ) SDL_calloc ( joystick - > nhats , sizeof ( Uint8 ) ) ;
2015-06-21 15:33:46 +00:00
}
if ( joystick - > nballs > 0 ) {
2016-12-23 01:33:45 +00:00
joystick - > balls = ( struct balldelta * ) SDL_calloc ( joystick - > nballs , sizeof ( * joystick - > balls ) ) ;
2015-06-21 15:33:46 +00:00
}
if ( joystick - > nbuttons > 0 ) {
2016-12-23 01:33:45 +00:00
joystick - > buttons = ( Uint8 * ) SDL_calloc ( joystick - > nbuttons , sizeof ( Uint8 ) ) ;
2015-06-21 15:33:46 +00: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 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 15:33:46 +00:00
return NULL ;
}
2017-01-04 07:39:28 +00: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 13:59:58 +00:00
joystick - > is_game_controller = SDL_IsGameController ( device_index ) ;
2015-06-21 15:33:46 +00:00
/* Add joystick to list */
+ + joystick - > ref_count ;
/* Link the joystick in the list */
joystick - > next = SDL_joysticks ;
SDL_joysticks = joystick ;
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2016-11-29 13:04:42 +00:00
2018-08-09 23:00:17 +00:00
driver - > Update ( joystick ) ;
2016-12-08 18:13:45 +00:00
2018-08-09 23:00:17 +00:00
return joystick ;
2015-06-21 15:33:46 +00:00
}
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
int
SDL_JoystickAttachVirtual ( SDL_JoystickType type ,
2020-11-15 14:10:15 +00:00
int naxes , int nbuttons , int nhats )
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
{
# if SDL_JOYSTICK_VIRTUAL
2020-11-15 14:10:15 +00:00
return SDL_JoystickAttachVirtualInner ( type , naxes , nbuttons , nhats ) ;
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
# else
return SDL_SetError ( " SDL not built with virtual-joystick support " ) ;
# endif
}
int
SDL_JoystickDetachVirtual ( int device_index )
{
# if SDL_JOYSTICK_VIRTUAL
SDL_JoystickDriver * driver ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
if ( driver = = & SDL_VIRTUAL_JoystickDriver ) {
const int result = SDL_JoystickDetachVirtualInner ( device_index ) ;
SDL_UnlockJoysticks ( ) ;
return result ;
}
}
SDL_UnlockJoysticks ( ) ;
return SDL_SetError ( " Virtual joystick not found at provided index " ) ;
# else
return SDL_SetError ( " SDL not built with virtual-joystick support " ) ;
# endif
}
SDL_bool
SDL_JoystickIsVirtual ( int device_index )
{
# if SDL_JOYSTICK_VIRTUAL
SDL_JoystickDriver * driver ;
int driver_device_index ;
SDL_bool is_virtual = SDL_FALSE ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & driver_device_index ) ) {
if ( driver = = & SDL_VIRTUAL_JoystickDriver ) {
is_virtual = SDL_TRUE ;
}
}
SDL_UnlockJoysticks ( ) ;
return is_virtual ;
# else
return SDL_FALSE ;
# endif
}
int
2020-11-17 01:36:47 +00:00
SDL_JoystickSetVirtualAxis ( SDL_Joystick * joystick , int axis , Sint16 value )
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
{
# if SDL_JOYSTICK_VIRTUAL
return SDL_JoystickSetVirtualAxisInner ( joystick , axis , value ) ;
# else
return SDL_SetError ( " SDL not built with virtual-joystick support " ) ;
# endif
}
int
2020-11-17 01:36:47 +00:00
SDL_JoystickSetVirtualButton ( SDL_Joystick * joystick , int button , Uint8 value )
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
{
# if SDL_JOYSTICK_VIRTUAL
return SDL_JoystickSetVirtualButtonInner ( joystick , button , value ) ;
# else
return SDL_SetError ( " SDL not built with virtual-joystick support " ) ;
# endif
}
int
2020-11-17 01:36:47 +00:00
SDL_JoystickSetVirtualHat ( SDL_Joystick * joystick , int hat , Uint8 value )
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
{
# if SDL_JOYSTICK_VIRTUAL
return SDL_JoystickSetVirtualHatInner ( joystick , hat , value ) ;
# else
return SDL_SetError ( " SDL not built with virtual-joystick support " ) ;
# endif
}
2015-06-21 15:33:46 +00:00
/*
* Checks to make sure the joystick is valid .
*/
2019-12-21 04:12:03 +00:00
SDL_bool
2020-11-17 01:36:47 +00:00
SDL_PrivateJoystickValid ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
2019-12-21 04:12:03 +00:00
SDL_bool valid ;
2015-06-21 15:33:46 +00:00
if ( joystick = = NULL ) {
SDL_SetError ( " Joystick hasn't been opened yet " ) ;
2019-12-21 04:12:03 +00:00
valid = SDL_FALSE ;
2015-06-21 15:33:46 +00:00
} else {
2019-12-21 04:12:03 +00:00
valid = SDL_TRUE ;
2015-06-21 15:33:46 +00:00
}
return valid ;
}
2020-05-29 20:37:21 +00:00
SDL_bool
SDL_PrivateJoystickGetAutoGamepadMapping ( int device_index , SDL_GamepadMapping * out )
{
SDL_JoystickDriver * driver ;
SDL_bool is_ok = SDL_FALSE ;
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & device_index ) ) {
is_ok = driver - > GetGamepadMapping ( device_index , out ) ;
}
SDL_UnlockJoysticks ( ) ;
return is_ok ;
}
2015-06-21 15:33:46 +00:00
/*
* Get the number of multi - dimensional axis controls on a joystick
*/
int
2020-11-17 01:36:47 +00:00
SDL_JoystickNumAxes ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return - 1 ;
2015-06-21 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
return joystick - > naxes ;
2015-06-21 15:33:46 +00:00
}
/*
* Get the number of hats on a joystick
*/
int
2020-11-17 01:36:47 +00:00
SDL_JoystickNumHats ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return - 1 ;
2015-06-21 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
return joystick - > nhats ;
2015-06-21 15:33:46 +00:00
}
/*
* Get the number of trackballs on a joystick
*/
int
2020-11-17 01:36:47 +00:00
SDL_JoystickNumBalls ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return - 1 ;
2015-06-21 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
return joystick - > nballs ;
2015-06-21 15:33:46 +00:00
}
/*
* Get the number of buttons on a joystick
*/
int
2020-11-17 01:36:47 +00:00
SDL_JoystickNumButtons ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return - 1 ;
2015-06-21 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
return joystick - > nbuttons ;
2015-06-21 15:33:46 +00:00
}
/*
* Get the current state of an axis control on a joystick
*/
Sint16
2020-11-17 01:36:47 +00:00
SDL_JoystickGetAxis ( SDL_Joystick * joystick , int axis )
2015-06-21 15:33:46 +00:00
{
Sint16 state ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return 0 ;
2015-06-21 15:33:46 +00:00
}
if ( axis < joystick - > naxes ) {
2016-12-23 01:33:45 +00:00
state = joystick - > axes [ axis ] . value ;
2015-06-21 15:33:46 +00:00
} else {
SDL_SetError ( " Joystick only has %d axes " , joystick - > naxes ) ;
state = 0 ;
}
2018-08-09 23:00:17 +00:00
return state ;
2015-06-21 15:33:46 +00:00
}
2017-01-04 18:28:07 +00:00
/*
* Get the initial state of an axis control on a joystick
*/
SDL_bool
2020-11-17 01:36:47 +00:00
SDL_JoystickGetAxisInitialState ( SDL_Joystick * joystick , int axis , Sint16 * state )
2017-01-04 18:28:07 +00:00
{
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 15:33:46 +00:00
/*
* Get the current state of a hat on a joystick
*/
Uint8
2020-11-17 01:36:47 +00:00
SDL_JoystickGetHat ( SDL_Joystick * joystick , int hat )
2015-06-21 15:33:46 +00:00
{
Uint8 state ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return 0 ;
2015-06-21 15:33:46 +00:00
}
if ( hat < joystick - > nhats ) {
state = joystick - > hats [ hat ] ;
} else {
SDL_SetError ( " Joystick only has %d hats " , joystick - > nhats ) ;
state = 0 ;
}
2018-08-09 23:00:17 +00:00
return state ;
2015-06-21 15:33:46 +00:00
}
/*
* Get the ball axis change since the last poll
*/
int
2020-11-17 01:36:47 +00:00
SDL_JoystickGetBall ( SDL_Joystick * joystick , int ball , int * dx , int * dy )
2015-06-21 15:33:46 +00:00
{
int retval ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return - 1 ;
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
return retval ;
2015-06-21 15:33:46 +00:00
}
/*
* Get the current state of a button on a joystick
*/
Uint8
2020-11-17 01:36:47 +00:00
SDL_JoystickGetButton ( SDL_Joystick * joystick , int button )
2015-06-21 15:33:46 +00:00
{
Uint8 state ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return 0 ;
2015-06-21 15:33:46 +00:00
}
if ( button < joystick - > nbuttons ) {
state = joystick - > buttons [ button ] ;
} else {
SDL_SetError ( " Joystick only has %d buttons " , joystick - > nbuttons ) ;
state = 0 ;
}
2018-08-09 23:00:17 +00:00
return state ;
2015-06-21 15:33:46 +00: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
2020-11-17 01:36:47 +00:00
SDL_JoystickGetAttached ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return SDL_FALSE ;
}
2018-08-09 23:03:50 +00:00
return joystick - > attached ;
2015-06-21 15:33:46 +00:00
}
/*
* Get the instance id for this opened joystick
*/
SDL_JoystickID
2020-11-17 01:36:47 +00:00
SDL_JoystickInstanceID ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return - 1 ;
2015-06-21 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
return joystick - > instance_id ;
2015-06-21 15:33:46 +00:00
}
2015-11-14 17:35:45 +00:00
/*
2019-12-21 04:12:03 +00:00
* Return the SDL_Joystick associated with an instance id .
2015-11-14 17:35:45 +00:00
*/
SDL_Joystick *
2019-12-21 04:12:03 +00:00
SDL_JoystickFromInstanceID ( SDL_JoystickID instance_id )
2015-11-14 17:35:45 +00:00
{
2016-11-29 13:04:42 +00:00
SDL_Joystick * joystick ;
2017-10-10 18:10:15 +00:00
SDL_LockJoysticks ( ) ;
2016-11-29 13:04:42 +00:00
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
2019-12-21 04:12:03 +00:00
if ( joystick - > instance_id = = instance_id ) {
break ;
}
}
SDL_UnlockJoysticks ( ) ;
return joystick ;
}
/**
* Return the SDL_Joystick associated with a player index .
*/
SDL_Joystick *
SDL_JoystickFromPlayerIndex ( int player_index )
{
SDL_JoystickID instance_id ;
SDL_Joystick * joystick ;
SDL_LockJoysticks ( ) ;
instance_id = SDL_GetJoystickIDForPlayerIndex ( player_index ) ;
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
if ( joystick - > instance_id = = instance_id ) {
2018-08-21 04:18:56 +00:00
break ;
2015-11-14 17:35:45 +00:00
}
}
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2018-08-21 04:18:56 +00:00
return joystick ;
2015-11-14 17:35:45 +00:00
}
2015-06-21 15:33:46 +00:00
/*
* Get the friendly name of this joystick
*/
const char *
2020-11-17 01:36:47 +00:00
SDL_JoystickName ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return NULL ;
2015-06-21 15:33:46 +00:00
}
2020-03-13 02:47:30 +00:00
return joystick - > name ;
2015-06-21 15:33:46 +00:00
}
2019-12-21 04:12:03 +00:00
/**
* Get the player index of an opened joystick , or - 1 if it ' s not available
*/
2018-10-25 23:53:14 +00:00
int
2020-11-17 01:36:47 +00:00
SDL_JoystickGetPlayerIndex ( SDL_Joystick * joystick )
2018-10-25 23:53:14 +00:00
{
2019-12-21 04:12:03 +00:00
int player_index ;
2018-10-25 23:53:14 +00:00
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return - 1 ;
}
2019-12-21 04:12:03 +00:00
SDL_LockJoysticks ( ) ;
player_index = SDL_GetPlayerIndexForJoystickID ( joystick - > instance_id ) ;
SDL_UnlockJoysticks ( ) ;
return player_index ;
}
/**
* Set the player index of an opened joystick
*/
void
2020-11-17 01:36:47 +00:00
SDL_JoystickSetPlayerIndex ( SDL_Joystick * joystick , int player_index )
2019-12-21 04:12:03 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return ;
}
SDL_LockJoysticks ( ) ;
SDL_SetJoystickIDForPlayerIndex ( player_index , joystick - > instance_id ) ;
SDL_UnlockJoysticks ( ) ;
2018-10-25 23:53:14 +00:00
}
2018-08-09 23:00:17 +00:00
int
2020-11-17 01:36:47 +00:00
SDL_JoystickRumble ( SDL_Joystick * joystick , Uint16 low_frequency_rumble , Uint16 high_frequency_rumble , Uint32 duration_ms )
2018-08-09 23:00:17 +00:00
{
2020-01-18 19:21:14 +00:00
int result ;
2020-01-14 06:05:54 +00:00
2018-08-09 23:00:17 +00:00
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return - 1 ;
}
2020-01-14 06:05:54 +00:00
2020-01-18 19:21:14 +00:00
SDL_LockJoysticks ( ) ;
2020-02-04 20:48:53 +00:00
if ( low_frequency_rumble = = joystick - > low_frequency_rumble & &
high_frequency_rumble = = joystick - > high_frequency_rumble ) {
/* Just update the expiration */
result = 0 ;
} else {
result = joystick - > driver - > Rumble ( joystick , low_frequency_rumble , high_frequency_rumble ) ;
}
/* Save the rumble value regardless of success, so we don't spam the driver */
joystick - > low_frequency_rumble = low_frequency_rumble ;
joystick - > high_frequency_rumble = high_frequency_rumble ;
if ( ( low_frequency_rumble | | high_frequency_rumble ) & & duration_ms ) {
joystick - > rumble_expiration = SDL_GetTicks ( ) + SDL_min ( duration_ms , SDL_MAX_RUMBLE_DURATION_MS ) ;
if ( ! joystick - > rumble_expiration ) {
joystick - > rumble_expiration = 1 ;
}
} else {
joystick - > rumble_expiration = 0 ;
}
2020-01-18 19:21:14 +00:00
SDL_UnlockJoysticks ( ) ;
2020-01-14 06:05:54 +00:00
2020-01-18 19:21:14 +00:00
return result ;
2018-08-09 23:00:17 +00:00
}
2020-11-12 02:57:37 +00:00
int
2020-11-17 01:36:47 +00:00
SDL_JoystickRumbleTriggers ( SDL_Joystick * joystick , Uint16 left_rumble , Uint16 right_rumble , Uint32 duration_ms )
2020-11-12 02:57:37 +00:00
{
int result ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return - 1 ;
}
SDL_LockJoysticks ( ) ;
if ( left_rumble = = joystick - > left_trigger_rumble & & right_rumble = = joystick - > right_trigger_rumble ) {
/* Just update the expiration */
result = 0 ;
} else {
result = joystick - > driver - > RumbleTriggers ( joystick , left_rumble , right_rumble ) ;
}
/* Save the rumble value regardless of success, so we don't spam the driver */
joystick - > left_trigger_rumble = left_rumble ;
joystick - > right_trigger_rumble = right_rumble ;
if ( ( left_rumble | | right_rumble ) & & duration_ms ) {
joystick - > trigger_rumble_expiration = SDL_GetTicks ( ) + SDL_min ( duration_ms , SDL_MAX_RUMBLE_DURATION_MS ) ;
if ( ! joystick - > trigger_rumble_expiration ) {
joystick - > trigger_rumble_expiration = 1 ;
}
} else {
joystick - > trigger_rumble_expiration = 0 ;
}
SDL_UnlockJoysticks ( ) ;
return result ;
}
2020-11-05 19:07:54 +00:00
SDL_bool
2020-11-17 01:36:47 +00:00
SDL_JoystickHasLED ( SDL_Joystick * joystick )
2020-11-05 19:07:54 +00:00
{
SDL_bool result ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return SDL_FALSE ;
}
SDL_LockJoysticks ( ) ;
result = joystick - > driver - > HasLED ( joystick ) ;
SDL_UnlockJoysticks ( ) ;
return result ;
}
2020-04-30 15:57:29 +00:00
int
2020-11-17 01:36:47 +00:00
SDL_JoystickSetLED ( SDL_Joystick * joystick , Uint8 red , Uint8 green , Uint8 blue )
2020-04-30 15:57:29 +00:00
{
int result ;
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return - 1 ;
}
SDL_LockJoysticks ( ) ;
if ( red = = joystick - > led_red & &
green = = joystick - > led_green & &
blue = = joystick - > led_blue ) {
/* Avoid spamming the driver */
result = 0 ;
} else {
result = joystick - > driver - > SetLED ( joystick , red , green , blue ) ;
}
/* Save the LED value regardless of success, so we don't spam the driver */
joystick - > led_red = red ;
joystick - > led_green = green ;
joystick - > led_blue = blue ;
SDL_UnlockJoysticks ( ) ;
return result ;
}
2015-06-21 15:33:46 +00:00
/*
* Close a joystick previously opened with SDL_JoystickOpen ( )
*/
void
2020-11-17 01:36:47 +00:00
SDL_JoystickClose ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
SDL_Joystick * joysticklist ;
SDL_Joystick * joysticklistprev ;
2020-11-14 02:01:29 +00:00
int i ;
2015-06-21 15:33:46 +00:00
2018-08-09 23:00:17 +00:00
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2015-06-21 15:33:46 +00:00
return ;
}
2017-10-10 18:10:15 +00:00
SDL_LockJoysticks ( ) ;
2016-11-29 13:04:42 +00:00
2015-06-21 15:33:46 +00:00
/* First decrement ref count */
if ( - - joystick - > ref_count > 0 ) {
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 15:33:46 +00:00
return ;
}
2016-12-14 14:25:09 +00:00
if ( SDL_updating_joystick ) {
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 15:33:46 +00:00
return ;
}
2020-02-04 20:48:53 +00:00
if ( joystick - > rumble_expiration ) {
SDL_JoystickRumble ( joystick , 0 , 0 , 0 ) ;
}
2020-11-12 02:57:37 +00:00
if ( joystick - > trigger_rumble_expiration ) {
SDL_JoystickRumbleTriggers ( joystick , 0 , 0 , 0 ) ;
}
2020-02-04 20:48:53 +00:00
2018-08-09 23:00:17 +00:00
joystick - > driver - > Close ( joystick ) ;
2015-06-21 15:33:46 +00: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 ) ;
2020-11-17 01:36:47 +00:00
SDL_free ( joystick - > serial ) ;
2015-06-21 15:33:46 +00:00
/* Free the data associated with this joystick */
SDL_free ( joystick - > axes ) ;
SDL_free ( joystick - > hats ) ;
SDL_free ( joystick - > balls ) ;
SDL_free ( joystick - > buttons ) ;
2020-11-14 02:01:29 +00:00
for ( i = 0 ; i < joystick - > ntouchpads ; i + + ) {
SDL_JoystickTouchpadInfo * touchpad = & joystick - > touchpads [ i ] ;
SDL_free ( touchpad - > fingers ) ;
}
SDL_free ( joystick - > touchpads ) ;
2020-11-24 14:40:13 +00:00
SDL_free ( joystick - > sensors ) ;
2015-06-21 15:33:46 +00:00
SDL_free ( joystick ) ;
2016-11-29 13:04:42 +00:00
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 15:33:46 +00:00
}
void
SDL_JoystickQuit ( void )
{
2018-08-09 23:00:17 +00:00
int i ;
2015-06-21 15:33:46 +00:00
/* Make sure we're not getting called in the middle of updating joysticks */
2017-10-10 18:10:15 +00:00
SDL_LockJoysticks ( ) ;
2019-03-27 15:17:05 +00:00
while ( SDL_updating_joystick ) {
SDL_UnlockJoysticks ( ) ;
SDL_Delay ( 1 ) ;
SDL_LockJoysticks ( ) ;
}
2016-11-29 13:04:42 +00:00
2015-06-21 15:33:46 +00:00
/* Stop the event polling */
while ( SDL_joysticks ) {
SDL_joysticks - > ref_count = 1 ;
SDL_JoystickClose ( SDL_joysticks ) ;
}
/* Quit the joystick setup */
2018-08-09 23:00:17 +00:00
for ( i = 0 ; i < SDL_arraysize ( SDL_joystick_drivers ) ; + + i ) {
SDL_joystick_drivers [ i ] - > Quit ( ) ;
}
2015-06-21 15:33:46 +00:00
2019-12-21 04:12:03 +00:00
if ( SDL_joystick_players ) {
SDL_free ( SDL_joystick_players ) ;
SDL_joystick_players = NULL ;
SDL_joystick_player_count = 0 ;
}
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2016-11-29 13:04:42 +00:00
2015-06-21 15:33:46 +00:00
# if !SDL_EVENTS_DISABLED
SDL_QuitSubSystem ( SDL_INIT_EVENTS ) ;
# endif
2016-11-29 13:04:42 +00:00
2017-08-09 18:59:29 +00:00
SDL_DelHintCallback ( SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS ,
SDL_JoystickAllowBackgroundEventsChanged , NULL ) ;
2016-11-29 13:04:42 +00:00
if ( SDL_joystick_lock ) {
2019-03-27 15:17:05 +00:00
SDL_mutex * mutex = SDL_joystick_lock ;
2016-11-29 13:04:42 +00:00
SDL_joystick_lock = NULL ;
2019-03-27 15:17:05 +00:00
SDL_DestroyMutex ( mutex ) ;
2016-11-29 13:04:42 +00:00
}
2017-08-09 18:59:29 +00:00
SDL_GameControllerQuitMappings ( ) ;
2015-06-21 15:33:46 +00:00
}
static SDL_bool
SDL_PrivateJoystickShouldIgnoreEvent ( )
{
if ( SDL_joystick_allows_background_events ) {
return SDL_FALSE ;
}
2017-08-13 00:41:59 +00: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 15:33:46 +00:00
}
return SDL_FALSE ;
}
/* These are global for SDL_sysjoystick.c and SDL_events.c */
2020-11-14 02:01:29 +00:00
void SDL_PrivateJoystickAddTouchpad ( SDL_Joystick * joystick , int nfingers )
{
int ntouchpads = joystick - > ntouchpads + 1 ;
2020-11-17 18:30:20 +00:00
SDL_JoystickTouchpadInfo * touchpads = ( SDL_JoystickTouchpadInfo * ) SDL_realloc ( joystick - > touchpads , ( ntouchpads * sizeof ( SDL_JoystickTouchpadInfo ) ) ) ;
2020-11-14 02:01:29 +00:00
if ( touchpads ) {
SDL_JoystickTouchpadInfo * touchpad = & touchpads [ ntouchpads - 1 ] ;
SDL_JoystickTouchpadFingerInfo * fingers = ( SDL_JoystickTouchpadFingerInfo * ) SDL_calloc ( nfingers , sizeof ( SDL_JoystickTouchpadFingerInfo ) ) ;
if ( fingers ) {
touchpad - > nfingers = nfingers ;
touchpad - > fingers = fingers ;
} else {
/* Out of memory, this touchpad won't be active */
touchpad - > nfingers = 0 ;
touchpad - > fingers = NULL ;
}
joystick - > ntouchpads = ntouchpads ;
joystick - > touchpads = touchpads ;
}
}
2020-11-17 18:30:20 +00:00
void SDL_PrivateJoystickAddSensor ( SDL_Joystick * joystick , SDL_SensorType type )
{
int nsensors = joystick - > nsensors + 1 ;
SDL_JoystickSensorInfo * sensors = ( SDL_JoystickSensorInfo * ) SDL_realloc ( joystick - > sensors , ( nsensors * sizeof ( SDL_JoystickSensorInfo ) ) ) ;
if ( sensors ) {
SDL_JoystickSensorInfo * sensor = & sensors [ nsensors - 1 ] ;
SDL_zerop ( sensor ) ;
sensor - > type = type ;
joystick - > nsensors = nsensors ;
joystick - > sensors = sensors ;
}
}
2018-08-09 23:00:17 +00:00
void SDL_PrivateJoystickAdded ( SDL_JoystickID device_instance )
2016-08-26 19:18:08 +00:00
{
2019-12-21 04:12:03 +00:00
SDL_JoystickDriver * driver ;
int driver_device_index ;
int player_index = - 1 ;
int device_index = SDL_JoystickGetDeviceIndexFromInstanceID ( device_instance ) ;
2018-08-09 23:00:17 +00:00
if ( device_index < 0 ) {
return ;
}
2016-08-26 19:18:08 +00:00
2019-12-21 04:12:03 +00:00
SDL_LockJoysticks ( ) ;
if ( SDL_GetDriverAndJoystickIndex ( device_index , & driver , & driver_device_index ) ) {
player_index = driver - > GetDevicePlayerIndex ( driver_device_index ) ;
}
if ( player_index < 0 & & SDL_IsGameController ( device_index ) ) {
player_index = SDL_FindFreePlayerIndex ( ) ;
}
if ( player_index > = 0 ) {
SDL_SetJoystickIDForPlayerIndex ( player_index , device_instance ) ;
}
SDL_UnlockJoysticks ( ) ;
# if !SDL_EVENTS_DISABLED
{
SDL_Event event ;
2016-08-26 19:18:08 +00:00
2019-12-21 04:12:03 +00:00
event . type = SDL_JOYDEVICEADDED ;
if ( SDL_GetEventState ( event . type ) = = SDL_ENABLE ) {
event . jdevice . which = device_index ;
SDL_PushEvent ( & event ) ;
}
2016-08-26 19:18:08 +00: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 .
*/
2020-08-29 23:50:26 +00:00
static void UpdateEventsForDeviceRemoval ( int device_index )
2016-08-26 19:18:08 +00:00
{
int i , num_events ;
SDL_Event * events ;
2018-10-23 00:50:32 +00:00
SDL_bool isstack ;
2016-08-26 19:18:08 +00:00
num_events = SDL_PeepEvents ( NULL , 0 , SDL_PEEKEVENT , SDL_JOYDEVICEADDED , SDL_JOYDEVICEADDED ) ;
if ( num_events < = 0 ) {
return ;
}
2018-10-23 00:50:32 +00:00
events = SDL_small_alloc ( SDL_Event , num_events , & isstack ) ;
2016-08-26 19:18:08 +00:00
if ( ! events ) {
return ;
}
num_events = SDL_PeepEvents ( events , num_events , SDL_GETEVENT , SDL_JOYDEVICEADDED , SDL_JOYDEVICEADDED ) ;
for ( i = 0 ; i < num_events ; + + i ) {
2020-08-29 23:50:26 +00:00
if ( events [ i ] . cdevice . which < device_index ) {
/* No change for index values lower than the removed device */
}
else if ( events [ i ] . cdevice . which = = device_index ) {
/* Drop this event entirely */
SDL_memmove ( & events [ i ] , & events [ i + 1 ] , sizeof ( * events ) * ( num_events - ( i + 1 ) ) ) ;
- - num_events ;
- - i ;
}
else {
/* Fix up the device index if greater than the removed device */
- - events [ i ] . cdevice . which ;
}
2016-08-26 19:18:08 +00:00
}
SDL_PeepEvents ( events , num_events , SDL_ADDEVENT , 0 , 0 ) ;
2018-10-23 00:50:32 +00:00
SDL_small_free ( events , isstack ) ;
2016-08-26 19:18:08 +00:00
}
2020-03-26 22:47:04 +00:00
static void
SDL_PrivateJoystickForceRecentering ( SDL_Joystick * joystick )
{
2020-11-14 02:01:29 +00:00
int i , j ;
2020-03-26 22:47:04 +00:00
/* Tell the app that everything is centered/unpressed... */
for ( i = 0 ; i < joystick - > naxes ; i + + ) {
if ( joystick - > axes [ i ] . has_initial_value ) {
SDL_PrivateJoystickAxis ( joystick , i , joystick - > axes [ i ] . zero ) ;
}
}
for ( i = 0 ; i < joystick - > nbuttons ; i + + ) {
2020-11-14 02:01:29 +00:00
SDL_PrivateJoystickButton ( joystick , i , SDL_RELEASED ) ;
2020-03-26 22:47:04 +00:00
}
for ( i = 0 ; i < joystick - > nhats ; i + + ) {
SDL_PrivateJoystickHat ( joystick , i , SDL_HAT_CENTERED ) ;
}
2020-11-14 02:01:29 +00:00
for ( i = 0 ; i < joystick - > ntouchpads ; i + + ) {
2020-11-15 14:10:15 +00:00
SDL_JoystickTouchpadInfo * touchpad = & joystick - > touchpads [ i ] ;
2020-11-14 02:01:29 +00:00
for ( j = 0 ; j < touchpad - > nfingers ; + + j ) {
SDL_PrivateJoystickTouchpad ( joystick , i , j , SDL_RELEASED , 0.0f , 0.0f , 0.0f ) ;
}
}
2020-03-26 22:47:04 +00:00
}
2016-08-26 19:18:08 +00:00
void SDL_PrivateJoystickRemoved ( SDL_JoystickID device_instance )
{
2020-03-26 22:47:04 +00:00
SDL_Joystick * joystick = NULL ;
2020-01-13 23:35:54 +00:00
int player_index ;
2020-08-29 23:50:26 +00:00
int device_index ;
2016-08-26 19:18:08 +00:00
# if !SDL_EVENTS_DISABLED
SDL_Event event ;
2020-03-26 22:47:04 +00:00
# endif
2016-08-26 19:18:08 +00:00
2020-03-26 22:47:04 +00:00
/* Find this joystick... */
2020-08-29 23:50:26 +00:00
device_index = 0 ;
2020-03-26 22:47:04 +00:00
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
if ( joystick - > instance_id = = device_instance ) {
SDL_PrivateJoystickForceRecentering ( joystick ) ;
joystick - > attached = SDL_FALSE ;
break ;
}
2020-08-29 23:50:26 +00:00
+ + device_index ;
2020-03-26 22:47:04 +00:00
}
# if !SDL_EVENTS_DISABLED
SDL_zero ( event ) ;
2016-08-26 19:18:08 +00:00
event . type = SDL_JOYDEVICEREMOVED ;
if ( SDL_GetEventState ( event . type ) = = SDL_ENABLE ) {
event . jdevice . which = device_instance ;
2017-10-11 00:41:41 +00:00
SDL_PushEvent ( & event ) ;
2016-08-26 19:18:08 +00:00
}
2020-08-29 23:50:26 +00:00
UpdateEventsForDeviceRemoval ( device_index ) ;
2016-08-26 19:18:08 +00:00
# endif /* !SDL_EVENTS_DISABLED */
2018-08-09 23:03:50 +00:00
2020-01-13 23:35:54 +00:00
SDL_LockJoysticks ( ) ;
player_index = SDL_GetPlayerIndexForJoystickID ( device_instance ) ;
if ( player_index > = 0 ) {
SDL_joystick_players [ player_index ] = - 1 ;
}
SDL_UnlockJoysticks ( ) ;
2016-08-26 19:18:08 +00:00
}
2015-06-21 15:33:46 +00:00
int
2020-11-17 01:36:47 +00:00
SDL_PrivateJoystickAxis ( SDL_Joystick * joystick , Uint8 axis , Sint16 value )
2015-06-21 15:33:46 +00:00
{
int posted ;
2019-11-28 19:44:15 +00:00
SDL_JoystickAxisInfo * info ;
2015-06-21 15:33:46 +00:00
/* Make sure we're not getting garbage or duplicate events */
if ( axis > = joystick - > naxes ) {
return 0 ;
}
2019-11-28 19:44:15 +00:00
info = & joystick - > axes [ axis ] ;
if ( ! info - > has_initial_value | |
2020-03-13 20:05:40 +00:00
( ! info - > has_second_value & & ( info - > initial_value < = - 32767 | | info - > initial_value = = 32767 ) & & SDL_abs ( value ) < ( SDL_JOYSTICK_AXIS_MAX / 4 ) ) ) {
2019-11-28 19:44:15 +00:00
info - > initial_value = value ;
info - > value = value ;
info - > zero = value ;
info - > has_initial_value = SDL_TRUE ;
2020-03-13 20:05:40 +00:00
} else if ( value = = info - > value ) {
return 0 ;
2019-11-28 19:44:15 +00:00
} else {
info - > has_second_value = SDL_TRUE ;
2017-01-04 07:39:28 +00:00
}
2019-11-28 19:44:15 +00:00
if ( ! info - > sent_initial_value ) {
2017-09-21 17:29:17 +00: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 */
2019-11-28 19:44:15 +00:00
if ( SDL_abs ( value - info - > value ) < = MAX_ALLOWED_JITTER ) {
2017-09-21 17:29:17 +00:00
return 0 ;
}
2019-11-28 19:44:15 +00:00
info - > sent_initial_value = SDL_TRUE ;
2020-03-13 20:05:40 +00:00
info - > value = ~ value ; /* Just so we pass the check above */
2019-11-28 19:44:15 +00:00
SDL_PrivateJoystickAxis ( joystick , axis , info - > initial_value ) ;
2016-12-23 01:33:45 +00:00
}
2015-06-21 15:33:46 +00:00
/* We ignore events if we don't have keyboard focus, except for centering
* events .
*/
if ( SDL_PrivateJoystickShouldIgnoreEvent ( ) ) {
2019-11-28 19:44:15 +00:00
if ( ( value > info - > zero & & value > = info - > value ) | |
( value < info - > zero & & value < = info - > value ) ) {
2015-06-21 15:33:46 +00:00
return 0 ;
}
}
/* Update internal joystick state */
2019-11-28 19:44:15 +00:00
info - > value = value ;
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
return posted ;
2015-06-21 15:33:46 +00:00
}
int
2020-11-17 01:36:47 +00:00
SDL_PrivateJoystickHat ( SDL_Joystick * joystick , Uint8 hat , Uint8 value )
2015-06-21 15:33:46 +00:00
{
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-09 23:00:17 +00:00
return posted ;
2015-06-21 15:33:46 +00:00
}
int
2020-11-17 01:36:47 +00:00
SDL_PrivateJoystickBall ( SDL_Joystick * joystick , Uint8 ball ,
2015-06-21 15:33:46 +00:00
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-09 23:00:17 +00:00
return posted ;
2015-06-21 15:33:46 +00:00
}
int
2020-11-17 01:36:47 +00:00
SDL_PrivateJoystickButton ( SDL_Joystick * joystick , Uint8 button , Uint8 state )
2015-06-21 15:33:46 +00:00
{
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-09 23:00:17 +00:00
return 0 ;
2015-06-21 15:33:46 +00:00
}
# endif /* !SDL_EVENTS_DISABLED */
/* Make sure we're not getting garbage or duplicate events */
if ( button > = joystick - > nbuttons ) {
return 0 ;
2015-09-30 22:39:30 +00:00
}
if ( state = = joystick - > buttons [ button ] ) {
return 0 ;
}
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
return posted ;
2015-06-21 15:33:46 +00:00
}
void
SDL_JoystickUpdate ( void )
{
2018-08-09 23:00:17 +00:00
int i ;
2019-10-23 06:50:57 +00:00
SDL_Joystick * joystick , * next ;
2016-11-29 13:04:42 +00:00
2018-11-20 05:17:00 +00:00
if ( ! SDL_WasInit ( SDL_INIT_JOYSTICK ) ) {
return ;
}
2017-10-10 18:10:15 +00:00
SDL_LockJoysticks ( ) ;
2015-06-21 15:33:46 +00:00
2016-12-08 18:13:45 +00:00
if ( SDL_updating_joystick ) {
/* The joysticks are already being updated */
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2016-12-08 18:13:45 +00:00
return ;
}
2016-12-14 14:25:09 +00:00
SDL_updating_joystick = SDL_TRUE ;
2015-06-21 15:33:46 +00:00
2016-12-14 14:25:09 +00:00
/* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2016-12-08 18:13:45 +00:00
2019-12-19 23:01:35 +00:00
# ifdef SDL_JOYSTICK_HIDAPI
/* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
HIDAPI_UpdateDevices ( ) ;
# endif /* SDL_JOYSTICK_HIDAPI */
2016-12-14 14:25:09 +00:00
for ( joystick = SDL_joysticks ; joystick ; joystick = joystick - > next ) {
2018-08-09 23:03:50 +00:00
if ( joystick - > attached ) {
2019-06-07 16:00:24 +00:00
/* This should always be true, but seeing a crash in the wild...? */
if ( joystick - > driver ) {
joystick - > driver - > Update ( joystick ) ;
}
2015-06-21 15:33:46 +00:00
2018-08-09 23:03:50 +00:00
if ( joystick - > delayed_guide_button ) {
SDL_GameControllerHandleDelayedGuideButton ( joystick ) ;
}
2018-03-19 21:42:51 +00:00
}
2020-02-04 20:48:53 +00:00
if ( joystick - > rumble_expiration ) {
SDL_LockJoysticks ( ) ;
/* Double check now that the lock is held */
if ( joystick - > rumble_expiration & &
SDL_TICKS_PASSED ( SDL_GetTicks ( ) , joystick - > rumble_expiration ) ) {
SDL_JoystickRumble ( joystick , 0 , 0 , 0 ) ;
}
SDL_UnlockJoysticks ( ) ;
}
2020-11-12 02:57:37 +00:00
if ( joystick - > trigger_rumble_expiration ) {
SDL_LockJoysticks ( ) ;
/* Double check now that the lock is held */
if ( joystick - > trigger_rumble_expiration & &
SDL_TICKS_PASSED ( SDL_GetTicks ( ) , joystick - > trigger_rumble_expiration ) ) {
SDL_JoystickRumbleTriggers ( joystick , 0 , 0 , 0 ) ;
}
SDL_UnlockJoysticks ( ) ;
}
2016-12-14 14:25:09 +00:00
}
2015-06-21 15:33:46 +00:00
2017-10-10 18:10:15 +00:00
SDL_LockJoysticks ( ) ;
2016-12-08 18:13:45 +00:00
2016-12-14 14:25:09 +00:00
SDL_updating_joystick = SDL_FALSE ;
2015-06-21 15:33:46 +00:00
2016-12-14 14:25:09 +00:00
/* If any joysticks were closed while updating, free them here */
2019-10-23 06:50:57 +00:00
for ( joystick = SDL_joysticks ; joystick ; joystick = next ) {
next = joystick - > next ;
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
for ( i = 0 ; i < SDL_arraysize ( SDL_joystick_drivers ) ; + + i ) {
SDL_joystick_drivers [ i ] - > Detect ( ) ;
}
2016-11-29 13:04:42 +00:00
2017-10-10 18:10:15 +00:00
SDL_UnlockJoysticks ( ) ;
2015-06-21 15:33:46 +00: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-09 23:00:17 +00:00
return state ;
2015-06-21 15:33:46 +00:00
# endif /* SDL_EVENTS_DISABLED */
}
2017-08-09 18:59:29 +00:00
void SDL_GetJoystickGUIDInfo ( SDL_JoystickGUID guid , Uint16 * vendor , Uint16 * product , Uint16 * version )
2016-11-11 01:19:34 +00: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 19:53:23 +00:00
guid16 [ 1 ] = = 0x0000 & &
2016-11-11 01:19:34 +00:00
/* guid16[2] is vendor ID */
2016-11-24 19:53:23 +00:00
guid16 [ 3 ] = = 0x0000 & &
2016-11-11 01:19:34 +00:00
/* guid16[4] is product ID */
2016-11-24 19:53:23 +00:00
guid16 [ 5 ] = = 0x0000
2016-11-11 01:19:34 +00:00
/* guid16[6] is product version */
2018-08-09 23:00:17 +00:00
) {
2016-11-11 01:19:34 +00: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 ;
}
}
}
2020-03-13 02:47:30 +00:00
static int
PrefixMatch ( const char * a , const char * b )
2019-12-14 00:07:25 +00:00
{
2020-03-13 02:47:30 +00:00
int matchlen = 0 ;
while ( * a & & * b ) {
2020-03-13 20:05:43 +00:00
if ( SDL_tolower ( * a + + ) = = SDL_tolower ( * b + + ) ) {
2020-03-13 02:47:30 +00:00
+ + matchlen ;
} else {
break ;
2019-12-14 00:07:25 +00:00
}
}
2020-03-13 02:47:30 +00:00
return matchlen ;
2019-12-14 00:07:25 +00:00
}
2020-03-13 02:47:30 +00:00
char *
SDL_CreateJoystickName ( Uint16 vendor , Uint16 product , const char * vendor_name , const char * product_name )
2019-12-12 01:47:01 +00:00
{
2020-03-13 02:47:30 +00:00
static struct {
const char * prefix ;
const char * replacement ;
} replacements [ ] = {
{ " NVIDIA Corporation " , " " } ,
{ " Performance Designed Products " , " PDP " } ,
2020-11-25 18:28:48 +00:00
{ " HORI CO.,LTD. " , " HORI " } ,
2020-03-13 02:47:30 +00:00
{ " HORI CO.,LTD " , " HORI " } ,
} ;
const char * custom_name ;
char * name ;
size_t i , len ;
custom_name = GuessControllerName ( vendor , product ) ;
if ( custom_name ) {
return SDL_strdup ( custom_name ) ;
}
if ( ! vendor_name ) {
vendor_name = " " ;
}
if ( ! product_name ) {
product_name = " " ;
}
while ( * vendor_name = = ' ' ) {
+ + vendor_name ;
}
while ( * product_name = = ' ' ) {
+ + product_name ;
}
if ( * vendor_name & & * product_name ) {
len = ( SDL_strlen ( vendor_name ) + 1 + SDL_strlen ( product_name ) + 1 ) ;
name = ( char * ) SDL_malloc ( len ) ;
if ( ! name ) {
return NULL ;
}
SDL_snprintf ( name , len , " %s %s " , vendor_name , product_name ) ;
} else if ( * product_name ) {
name = SDL_strdup ( product_name ) ;
} else if ( vendor | | product ) {
len = ( 6 + 1 + 6 + 1 ) ;
name = ( char * ) SDL_malloc ( len ) ;
if ( ! name ) {
return NULL ;
}
SDL_snprintf ( name , len , " 0x%.4x/0x%.4x " , vendor , product ) ;
} else {
name = SDL_strdup ( " Controller " ) ;
}
/* Trim trailing whitespace */
for ( len = SDL_strlen ( name ) ; ( len > 0 & & name [ len - 1 ] = = ' ' ) ; - - len ) {
/* continue */
}
name [ len ] = ' \0 ' ;
/* Compress duplicate spaces */
for ( i = 0 ; i < ( len - 1 ) ; ) {
if ( name [ i ] = = ' ' & & name [ i + 1 ] = = ' ' ) {
SDL_memmove ( & name [ i ] , & name [ i + 1 ] , ( len - i ) ) ;
- - len ;
} else {
+ + i ;
}
}
2020-03-13 20:05:43 +00:00
/* Remove duplicate manufacturer or product in the name */
for ( i = 1 ; i < ( len - 1 ) ; + + i ) {
2020-03-13 02:47:30 +00:00
int matchlen = PrefixMatch ( name , & name [ i ] ) ;
2020-03-13 20:05:43 +00:00
if ( matchlen > 0 & & name [ matchlen - 1 ] = = ' ' ) {
2020-03-13 02:47:30 +00:00
SDL_memmove ( name , name + matchlen , len - matchlen + 1 ) ;
len - = matchlen ;
break ;
2020-03-13 20:05:43 +00:00
} else if ( matchlen > 0 & & name [ matchlen ] = = ' ' ) {
SDL_memmove ( name , name + matchlen + 1 , len - matchlen ) ;
len - = ( matchlen + 1 ) ;
break ;
2020-03-13 02:47:30 +00:00
}
}
/* Perform any manufacturer replacements */
for ( i = 0 ; i < SDL_arraysize ( replacements ) ; + + i ) {
size_t prefixlen = SDL_strlen ( replacements [ i ] . prefix ) ;
if ( SDL_strncasecmp ( name , replacements [ i ] . prefix , prefixlen ) = = 0 ) {
size_t replacementlen = SDL_strlen ( replacements [ i ] . replacement ) ;
SDL_memcpy ( name , replacements [ i ] . replacement , replacementlen ) ;
SDL_memmove ( name + replacementlen , name + prefixlen , ( len - prefixlen + 1 ) ) ;
break ;
}
}
return name ;
2019-12-12 01:47:01 +00:00
}
2020-11-25 06:25:26 +00:00
SDL_GameControllerType
SDL_GetJoystickGameControllerTypeFromVIDPID ( Uint16 vendor , Uint16 product )
{
return SDL_GetJoystickGameControllerType ( NULL , vendor , product , - 1 , 0 , 0 , 0 ) ;
}
2019-11-22 21:12:12 +00:00
SDL_GameControllerType
2019-11-22 22:09:24 +00:00
SDL_GetJoystickGameControllerTypeFromGUID ( SDL_JoystickGUID guid , const char * name )
2019-10-17 23:59:05 +00:00
{
2019-11-22 21:12:12 +00:00
SDL_GameControllerType type ;
Uint16 vendor , product ;
2019-10-17 23:59:05 +00:00
2019-11-22 21:12:12 +00:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , & product , NULL ) ;
2020-01-18 19:21:14 +00:00
type = SDL_GetJoystickGameControllerType ( name , vendor , product , - 1 , 0 , 0 , 0 ) ;
2019-11-22 21:12:12 +00:00
if ( type = = SDL_CONTROLLER_TYPE_UNKNOWN ) {
if ( SDL_IsJoystickXInput ( guid ) ) {
/* This is probably an Xbox One controller */
return SDL_CONTROLLER_TYPE_XBOXONE ;
}
}
return type ;
2018-08-09 23:00:17 +00:00
}
2019-11-22 21:12:12 +00:00
SDL_GameControllerType
2020-01-18 19:21:14 +00:00
SDL_GetJoystickGameControllerType ( const char * name , Uint16 vendor , Uint16 product , int interface_number , int interface_class , int interface_subclass , int interface_protocol )
2018-08-09 23:00:17 +00:00
{
2020-02-19 16:26:00 +00:00
static const int LIBUSB_CLASS_VENDOR_SPEC = 0xFF ;
static const int XB360_IFACE_SUBCLASS = 93 ;
static const int XB360_IFACE_PROTOCOL = 1 ; /* Wired */
static const int XB360W_IFACE_PROTOCOL = 129 ; /* Wireless */
static const int XBONE_IFACE_SUBCLASS = 71 ;
static const int XBONE_IFACE_PROTOCOL = 208 ;
2020-01-18 19:21:14 +00:00
SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN ;
2020-02-19 16:26:00 +00:00
/* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
if ( interface_class = = LIBUSB_CLASS_VENDOR_SPEC & &
interface_subclass = = XB360_IFACE_SUBCLASS & &
( interface_protocol = = XB360_IFACE_PROTOCOL | |
interface_protocol = = XB360W_IFACE_PROTOCOL ) ) {
static const int SUPPORTED_VENDORS [ ] = {
0x0079 , /* GPD Win 2 */
0x044f , /* Thrustmaster */
0x045e , /* Microsoft */
0x046d , /* Logitech */
0x056e , /* Elecom */
0x06a3 , /* Saitek */
0x0738 , /* Mad Catz */
0x07ff , /* Mad Catz */
0x0e6f , /* PDP */
0x0f0d , /* Hori */
0x1038 , /* SteelSeries */
0x11c9 , /* Nacon */
0x12ab , /* Unknown */
0x1430 , /* RedOctane */
0x146b , /* BigBen */
0x1532 , /* Razer Sabertooth */
0x15e4 , /* Numark */
0x162e , /* Joytech */
0x1689 , /* Razer Onza */
0x1bad , /* Harmonix */
0x24c6 , /* PowerA */
} ;
int i ;
for ( i = 0 ; i < SDL_arraysize ( SUPPORTED_VENDORS ) ; + + i ) {
if ( vendor = = SUPPORTED_VENDORS [ i ] ) {
type = SDL_CONTROLLER_TYPE_XBOX360 ;
break ;
}
2020-01-18 19:21:14 +00:00
}
2020-02-19 16:26:00 +00:00
}
2020-01-18 19:21:14 +00:00
2020-02-19 16:26:00 +00:00
if ( interface_number = = 0 & &
interface_class = = LIBUSB_CLASS_VENDOR_SPEC & &
interface_subclass = = XBONE_IFACE_SUBCLASS & &
interface_protocol = = XBONE_IFACE_PROTOCOL ) {
2020-01-18 19:21:14 +00:00
2020-02-19 16:26:00 +00:00
static const int SUPPORTED_VENDORS [ ] = {
0x045e , /* Microsoft */
0x0738 , /* Mad Catz */
0x0e6f , /* PDP */
0x0f0d , /* Hori */
0x1532 , /* Razer Wildcat */
0x24c6 , /* PowerA */
0x2e24 , /* Hyperkin */
} ;
int i ;
for ( i = 0 ; i < SDL_arraysize ( SUPPORTED_VENDORS ) ; + + i ) {
if ( vendor = = SUPPORTED_VENDORS [ i ] ) {
type = SDL_CONTROLLER_TYPE_XBOXONE ;
break ;
}
2019-11-22 22:09:24 +00:00
}
2018-09-24 18:49:25 +00:00
}
2020-01-18 19:21:14 +00:00
if ( type = = SDL_CONTROLLER_TYPE_UNKNOWN ) {
2020-02-19 16:26:00 +00:00
if ( vendor = = 0x0000 & & product = = 0x0000 ) {
/* Some devices are only identifiable by their name */
2020-11-06 19:30:52 +00:00
if ( name & &
( SDL_strcmp ( name , " Lic Pro Controller " ) = = 0 | |
SDL_strcmp ( name , " Nintendo Wireless Gamepad " ) = = 0 | |
SDL_strcmp ( name , " Wireless Gamepad " ) = = 0 ) ) {
2020-02-19 16:26:00 +00:00
/* HORI or PowerA Switch Pro Controller clone */
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO ;
2020-11-06 19:30:52 +00:00
} else if ( name & & SDL_strcmp ( name , " Virtual Joystick " ) = = 0 ) {
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
type = SDL_CONTROLLER_TYPE_VIRTUAL ;
2020-02-19 16:26:00 +00:00
} else {
type = SDL_CONTROLLER_TYPE_UNKNOWN ;
2020-01-18 19:21:14 +00:00
}
2020-02-19 16:26:00 +00:00
} else if ( vendor = = 0x0001 & & product = = 0x0001 ) {
type = SDL_CONTROLLER_TYPE_UNKNOWN ;
} else {
switch ( GuessControllerType ( vendor , product ) ) {
case k_eControllerType_XBox360Controller :
type = SDL_CONTROLLER_TYPE_XBOX360 ;
break ;
case k_eControllerType_XBoxOneController :
type = SDL_CONTROLLER_TYPE_XBOXONE ;
break ;
case k_eControllerType_PS3Controller :
type = SDL_CONTROLLER_TYPE_PS3 ;
break ;
case k_eControllerType_PS4Controller :
type = SDL_CONTROLLER_TYPE_PS4 ;
break ;
2020-11-05 23:02:54 +00:00
case k_eControllerType_PS5Controller :
type = SDL_CONTROLLER_TYPE_PS5 ;
break ;
2020-02-19 16:26:00 +00:00
case k_eControllerType_SwitchProController :
case k_eControllerType_SwitchInputOnlyController :
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO ;
break ;
default :
type = SDL_CONTROLLER_TYPE_UNKNOWN ;
break ;
2020-01-18 19:21:14 +00:00
}
}
}
return type ;
2018-08-09 23:00:17 +00:00
}
2020-11-06 19:30:52 +00:00
SDL_bool
SDL_IsJoystickXboxOneElite ( Uint16 vendor_id , Uint16 product_id )
{
if ( vendor_id = = USB_VENDOR_MICROSOFT ) {
if ( product_id = = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 | |
2020-11-10 06:39:33 +00:00
product_id = = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 | |
product_id = = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH ) {
2020-11-06 19:30:52 +00:00
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2020-11-10 20:26:30 +00:00
SDL_bool
SDL_IsJoystickXboxOneSeriesX ( Uint16 vendor_id , Uint16 product_id )
{
if ( vendor_id = = USB_VENDOR_MICROSOFT ) {
if ( product_id = = USB_PRODUCT_XBOX_ONE_SERIES_X | |
product_id = = USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH ) {
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2020-11-06 19:30:52 +00:00
SDL_bool
SDL_IsJoystickPS4 ( Uint16 vendor_id , Uint16 product_id )
{
EControllerType eType = GuessControllerType ( vendor_id , product_id ) ;
return ( eType = = k_eControllerType_PS4Controller ) ;
}
2018-08-09 23:00:17 +00:00
SDL_bool
2020-11-05 23:02:54 +00:00
SDL_IsJoystickPS5 ( Uint16 vendor_id , Uint16 product_id )
{
EControllerType eType = GuessControllerType ( vendor_id , product_id ) ;
return ( eType = = k_eControllerType_PS5Controller ) ;
}
2020-11-06 19:30:52 +00:00
SDL_bool
SDL_IsJoystickNintendoSwitchPro ( Uint16 vendor_id , Uint16 product_id )
{
EControllerType eType = GuessControllerType ( vendor_id , product_id ) ;
return ( eType = = k_eControllerType_SwitchProController | |
eType = = k_eControllerType_SwitchInputOnlyController ) ;
}
2020-11-05 23:02:54 +00:00
SDL_bool
SDL_IsJoystickNintendoSwitchProInputOnly ( Uint16 vendor_id , Uint16 product_id )
2019-11-22 21:12:12 +00:00
{
2020-11-05 23:02:54 +00:00
EControllerType eType = GuessControllerType ( vendor_id , product_id ) ;
2019-11-22 21:12:12 +00:00
return ( eType = = k_eControllerType_SwitchInputOnlyController ) ;
}
SDL_bool
2020-11-05 23:02:54 +00:00
SDL_IsJoystickSteamController ( Uint16 vendor_id , Uint16 product_id )
2018-08-09 23:00:17 +00:00
{
2020-11-05 23:02:54 +00:00
EControllerType eType = GuessControllerType ( vendor_id , product_id ) ;
2019-11-22 21:12:12 +00:00
return ( eType = = k_eControllerType_SteamController | |
eType = = k_eControllerType_SteamControllerV2 ) ;
2018-08-09 23:00:17 +00:00
}
2018-09-17 18:35:22 +00:00
SDL_bool
SDL_IsJoystickXInput ( SDL_JoystickGUID guid )
{
return ( guid . data [ 14 ] = = ' x ' ) ? SDL_TRUE : SDL_FALSE ;
}
2020-04-19 04:41:37 +00:00
SDL_bool
SDL_IsJoystickWGI ( SDL_JoystickGUID guid )
{
return ( guid . data [ 14 ] = = ' w ' ) ? SDL_TRUE : SDL_FALSE ;
}
2018-09-17 18:35:22 +00:00
SDL_bool
SDL_IsJoystickHIDAPI ( SDL_JoystickGUID guid )
{
return ( guid . data [ 14 ] = = ' h ' ) ? SDL_TRUE : SDL_FALSE ;
}
2020-03-16 19:23:38 +00:00
SDL_bool
SDL_IsJoystickRAWINPUT ( SDL_JoystickGUID guid )
{
return ( guid . data [ 14 ] = = ' r ' ) ? SDL_TRUE : SDL_FALSE ;
}
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
SDL_bool
SDL_IsJoystickVirtual ( SDL_JoystickGUID guid )
{
return ( guid . data [ 14 ] = = ' v ' ) ? SDL_TRUE : SDL_FALSE ;
}
2017-01-31 20:23:29 +00:00
static SDL_bool SDL_IsJoystickProductWheel ( Uint32 vidpid )
2017-01-27 13:59:58 +00: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 */
2020-04-24 21:03:30 +00:00
MAKE_VIDPID ( 0x046d , 0xc24f ) , /* Logitech G29 */
2017-01-27 13:59:58 +00:00
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 14:05:50 +00:00
MAKE_VIDPID ( 0x044f , 0xb66d ) , /* Thrustmaster Wheel FFB */
2017-01-27 13:59:58 +00: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 18:20:09 +00:00
if ( vidpid = = wheel_joysticks [ i ] ) {
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2017-01-31 20:23:29 +00:00
static SDL_bool SDL_IsJoystickProductFlightStick ( Uint32 vidpid )
2017-01-31 18:20:09 +00:00
{
static Uint32 flightstick_joysticks [ ] = {
2017-01-31 20:30:55 +00:00
MAKE_VIDPID ( 0x044f , 0x0402 ) , /* HOTAS Warthog Joystick */
MAKE_VIDPID ( 0x0738 , 0x2221 ) , /* Saitek Pro Flight X-56 Rhino Stick */
2017-01-31 18:20:09 +00:00
} ;
int i ;
for ( i = 0 ; i < SDL_arraysize ( flightstick_joysticks ) ; + + i ) {
if ( vidpid = = flightstick_joysticks [ i ] ) {
2017-01-27 13:59:58 +00:00
return SDL_TRUE ;
}
}
return SDL_FALSE ;
}
2017-01-31 20:23:29 +00:00
static SDL_bool SDL_IsJoystickProductThrottle ( Uint32 vidpid )
{
static Uint32 throttle_joysticks [ ] = {
2017-01-31 20:30:55 +00:00
MAKE_VIDPID ( 0x044f , 0x0404 ) , /* HOTAS Warthog Throttle */
MAKE_VIDPID ( 0x0738 , 0xa221 ) , /* Saitek Pro Flight X-56 Rhino Throttle */
2017-01-31 20:23:29 +00: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 13:59:58 +00:00
static SDL_JoystickType SDL_GetJoystickGUIDType ( SDL_JoystickGUID guid )
{
2017-01-31 18:20:09 +00:00
Uint16 vendor ;
Uint16 product ;
Uint32 vidpid ;
2018-09-17 18:35:22 +00:00
if ( SDL_IsJoystickXInput ( guid ) ) {
2017-01-27 13:59:58 +00: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 ;
}
}
2020-04-19 04:41:37 +00:00
if ( SDL_IsJoystickWGI ( guid ) ) {
return ( SDL_JoystickType ) guid . data [ 15 ] ;
}
Fixed bug 5028 - Virtual Joysticks (new joystick backend)
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!
2020-03-14 02:08:45 +00:00
if ( SDL_IsJoystickVirtual ( guid ) ) {
return ( SDL_JoystickType ) guid . data [ 15 ] ;
}
2017-01-31 18:20:09 +00:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , & product , NULL ) ;
vidpid = MAKE_VIDPID ( vendor , product ) ;
2017-01-31 20:23:29 +00:00
if ( SDL_IsJoystickProductWheel ( vidpid ) ) {
2017-01-27 13:59:58 +00:00
return SDL_JOYSTICK_TYPE_WHEEL ;
}
2017-01-31 20:23:29 +00:00
if ( SDL_IsJoystickProductFlightStick ( vidpid ) ) {
2017-01-31 18:20:09 +00:00
return SDL_JOYSTICK_TYPE_FLIGHT_STICK ;
}
2017-01-31 20:23:29 +00:00
if ( SDL_IsJoystickProductThrottle ( vidpid ) ) {
return SDL_JOYSTICK_TYPE_THROTTLE ;
}
2018-08-09 23:00:17 +00:00
if ( GuessControllerType ( vendor , product ) ! = k_eControllerType_UnknownNonSteamController ) {
return SDL_JOYSTICK_TYPE_GAMECONTROLLER ;
}
2017-01-27 13:59:58 +00:00
return SDL_JOYSTICK_TYPE_UNKNOWN ;
}
2018-08-09 23:00:17 +00: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 )
{
2020-03-03 01:31:58 +00:00
/* This list is taken from:
2018-12-05 22:46:03 +00:00
https : //raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py
*/
static Uint32 joystick_blacklist [ ] = {
2020-03-13 20:05:43 +00:00
/* Microsoft Microsoft Wireless Optical Desktop 2.10 */
2018-12-05 22:46:03 +00:00
/* Microsoft Wireless Desktop - Comfort Edition */
MAKE_VIDPID ( 0x045e , 0x009d ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft Microsoft Digital Media Pro Keyboard */
2018-12-05 22:46:03 +00:00
/* Microsoft Corp. Digital Media Pro Keyboard */
MAKE_VIDPID ( 0x045e , 0x00b0 ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft Microsoft Digital Media Keyboard */
2018-12-05 22:46:03 +00:00
/* Microsoft Corp. Digital Media Keyboard 1.0A */
MAKE_VIDPID ( 0x045e , 0x00b4 ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft Microsoft Digital Media Keyboard 3000 */
2018-12-05 22:46:03 +00:00
MAKE_VIDPID ( 0x045e , 0x0730 ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft Microsoft 2.4GHz Transceiver v6.0 */
/* Microsoft Microsoft 2.4GHz Transceiver v8.0 */
2018-12-05 22:46:03 +00:00
/* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */
/* Microsoft Wireless Mobile Mouse 1000 */
/* Microsoft Wireless Desktop 3000 */
MAKE_VIDPID ( 0x045e , 0x0745 ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft SideWinder(TM) 2.4GHz Transceiver */
2018-12-05 22:46:03 +00:00
MAKE_VIDPID ( 0x045e , 0x0748 ) ,
/* Microsoft Corp. Wired Keyboard 600 */
MAKE_VIDPID ( 0x045e , 0x0750 ) ,
/* Microsoft Corp. Sidewinder X4 keyboard */
MAKE_VIDPID ( 0x045e , 0x0768 ) ,
/* Microsoft Corp. Arc Touch Mouse Transceiver */
MAKE_VIDPID ( 0x045e , 0x0773 ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft 2.4GHz Transceiver v9.0 */
/* Microsoft Nano Transceiver v2.1 */
2018-12-05 22:46:03 +00:00
/* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */
MAKE_VIDPID ( 0x045e , 0x07a5 ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft Nano Transceiver v1.0 */
2018-12-05 22:46:03 +00:00
/* Microsoft Wireless Keyboard 800 */
MAKE_VIDPID ( 0x045e , 0x07b2 ) ,
2020-03-13 20:05:43 +00:00
/* Microsoft Nano Transceiver v2.0 */
2018-12-05 22:46:03 +00:00
MAKE_VIDPID ( 0x045e , 0x0800 ) ,
MAKE_VIDPID ( 0x046d , 0xc30a ) , /* Logitech, Inc. iTouch Composite keboard */
MAKE_VIDPID ( 0x04d9 , 0xa0df ) , /* Tek Syndicate Mouse (E-Signal USB Gaming Mouse) */
/* List of Wacom devices at: http://linuxwacom.sourceforge.net/wiki/index.php/Device_IDs */
MAKE_VIDPID ( 0x056a , 0x0010 ) , /* Wacom ET-0405 Graphire */
MAKE_VIDPID ( 0x056a , 0x0011 ) , /* Wacom ET-0405A Graphire2 (4x5) */
MAKE_VIDPID ( 0x056a , 0x0012 ) , /* Wacom ET-0507A Graphire2 (5x7) */
MAKE_VIDPID ( 0x056a , 0x0013 ) , /* Wacom CTE-430 Graphire3 (4x5) */
MAKE_VIDPID ( 0x056a , 0x0014 ) , /* Wacom CTE-630 Graphire3 (6x8) */
MAKE_VIDPID ( 0x056a , 0x0015 ) , /* Wacom CTE-440 Graphire4 (4x5) */
MAKE_VIDPID ( 0x056a , 0x0016 ) , /* Wacom CTE-640 Graphire4 (6x8) */
MAKE_VIDPID ( 0x056a , 0x0017 ) , /* Wacom CTE-450 Bamboo Fun (4x5) */
MAKE_VIDPID ( 0x056a , 0x0018 ) , /* Wacom CTE-650 Bamboo Fun 6x8 */
MAKE_VIDPID ( 0x056a , 0x0019 ) , /* Wacom CTE-631 Bamboo One */
MAKE_VIDPID ( 0x056a , 0x00d1 ) , /* Wacom Bamboo Pen and Touch CTH-460 */
MAKE_VIDPID ( 0x056a , 0x030e ) , /* Wacom Intuos Pen (S) CTL-480 */
MAKE_VIDPID ( 0x09da , 0x054f ) , /* A4 Tech Co., G7 750 mouse */
MAKE_VIDPID ( 0x09da , 0x1410 ) , /* A4 Tech Co., Ltd Bloody AL9 mouse */
MAKE_VIDPID ( 0x09da , 0x3043 ) , /* A4 Tech Co., Ltd Bloody R8A Gaming Mouse */
MAKE_VIDPID ( 0x09da , 0x31b5 ) , /* A4 Tech Co., Ltd Bloody TL80 Terminator Laser Gaming Mouse */
MAKE_VIDPID ( 0x09da , 0x3997 ) , /* A4 Tech Co., Ltd Bloody RT7 Terminator Wireless */
MAKE_VIDPID ( 0x09da , 0x3f8b ) , /* A4 Tech Co., Ltd Bloody V8 mouse */
MAKE_VIDPID ( 0x09da , 0x51f4 ) , /* Modecom MC-5006 Keyboard */
MAKE_VIDPID ( 0x09da , 0x5589 ) , /* A4 Tech Co., Ltd Terminator TL9 Laser Gaming Mouse */
MAKE_VIDPID ( 0x09da , 0x7b22 ) , /* A4 Tech Co., Ltd Bloody V5 */
MAKE_VIDPID ( 0x09da , 0x7f2d ) , /* A4 Tech Co., Ltd Bloody R3 mouse */
MAKE_VIDPID ( 0x09da , 0x8090 ) , /* A4 Tech Co., Ltd X-718BK Oscar Optical Gaming Mouse */
MAKE_VIDPID ( 0x09da , 0x9033 ) , /* A4 Tech Co., X7 X-705K */
MAKE_VIDPID ( 0x09da , 0x9066 ) , /* A4 Tech Co., Sharkoon Fireglider Optical */
MAKE_VIDPID ( 0x09da , 0x9090 ) , /* A4 Tech Co., Ltd XL-730K / XL-750BK / XL-755BK Laser Mouse */
MAKE_VIDPID ( 0x09da , 0x90c0 ) , /* A4 Tech Co., Ltd X7 G800V keyboard */
MAKE_VIDPID ( 0x09da , 0xf012 ) , /* A4 Tech Co., Ltd Bloody V7 mouse */
MAKE_VIDPID ( 0x09da , 0xf32a ) , /* A4 Tech Co., Ltd Bloody B540 keyboard */
MAKE_VIDPID ( 0x09da , 0xf613 ) , /* A4 Tech Co., Ltd Bloody V2 mouse */
MAKE_VIDPID ( 0x09da , 0xf624 ) , /* A4 Tech Co., Ltd Bloody B120 Keyboard */
MAKE_VIDPID ( 0x1b1c , 0x1b3c ) , /* Corsair Harpoon RGB gaming mouse */
MAKE_VIDPID ( 0x1d57 , 0xad03 ) , /* [T3] 2.4GHz and IR Air Mouse Remote Control */
MAKE_VIDPID ( 0x1e7d , 0x2e4a ) , /* Roccat Tyon Mouse */
MAKE_VIDPID ( 0x20a0 , 0x422d ) , /* Winkeyless.kr Keyboards */
MAKE_VIDPID ( 0x2516 , 0x001f ) , /* Cooler Master Storm Mizar Mouse */
MAKE_VIDPID ( 0x2516 , 0x0028 ) , /* Cooler Master Storm Alcor Mouse */
} ;
unsigned int i ;
Uint32 id ;
2018-08-09 23:00:17 +00:00
Uint16 vendor ;
Uint16 product ;
2020-11-24 02:27:43 +00:00
SDL_GameControllerType type ;
2018-08-09 23:00:17 +00:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , & product , NULL ) ;
2018-12-05 22:46:03 +00:00
/* Check the joystick blacklist */
id = MAKE_VIDPID ( vendor , product ) ;
for ( i = 0 ; i < SDL_arraysize ( joystick_blacklist ) ; + + i ) {
if ( id = = joystick_blacklist [ i ] ) {
return SDL_TRUE ;
}
}
2020-11-24 02:27:43 +00:00
type = SDL_GetJoystickGameControllerType ( name , vendor , product , - 1 , 0 , 0 , 0 ) ;
if ( ( type = = SDL_CONTROLLER_TYPE_PS4 | | type = = SDL_CONTROLLER_TYPE_PS5 ) & & SDL_IsPS4RemapperRunning ( ) ) {
2018-08-09 23:00:17 +00:00
return SDL_TRUE ;
}
if ( SDL_IsGameControllerNameAndGUID ( name , guid ) & &
SDL_ShouldIgnoreGameController ( name , guid ) ) {
return SDL_TRUE ;
}
return SDL_FALSE ;
}
2015-06-21 15:33:46 +00:00
/* return the guid for this index */
SDL_JoystickGUID SDL_JoystickGetDeviceGUID ( int device_index )
{
2018-08-09 23:00:17 +00: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 15:33:46 +00:00
}
2018-08-09 23:00:17 +00:00
SDL_UnlockJoysticks ( ) ;
return guid ;
2015-06-21 15:33:46 +00:00
}
2016-11-11 01:19:34 +00:00
Uint16 SDL_JoystickGetDeviceVendor ( int device_index )
{
Uint16 vendor ;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID ( device_index ) ;
2017-01-27 13:59:58 +00:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , NULL , NULL ) ;
2016-11-11 01:19:34 +00:00
return vendor ;
}
Uint16 SDL_JoystickGetDeviceProduct ( int device_index )
{
Uint16 product ;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID ( device_index ) ;
2017-01-27 13:59:58 +00:00
SDL_GetJoystickGUIDInfo ( guid , NULL , & product , NULL ) ;
2016-11-11 01:19:34 +00:00
return product ;
}
Uint16 SDL_JoystickGetDeviceProductVersion ( int device_index )
{
Uint16 version ;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID ( device_index ) ;
2017-01-27 13:59:58 +00:00
SDL_GetJoystickGUIDInfo ( guid , NULL , NULL , & version ) ;
2016-11-11 01:19:34 +00:00
return version ;
}
2017-01-27 13:59:58 +00: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 00:09:16 +00:00
SDL_JoystickID SDL_JoystickGetDeviceInstanceID ( int device_index )
{
2018-08-09 23:00:17 +00: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 00:09:16 +00:00
}
2018-08-09 23:00:17 +00:00
SDL_UnlockJoysticks ( ) ;
return device_index ;
2017-03-10 00:09:16 +00:00
}
2020-11-17 01:36:47 +00:00
SDL_JoystickGUID SDL_JoystickGetGUID ( SDL_Joystick * joystick )
2015-06-21 15:33:46 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
SDL_JoystickGUID emptyGUID ;
SDL_zero ( emptyGUID ) ;
return emptyGUID ;
}
2018-08-09 23:00:17 +00:00
return joystick - > guid ;
2015-06-21 15:33:46 +00:00
}
2020-11-17 01:36:47 +00:00
Uint16 SDL_JoystickGetVendor ( SDL_Joystick * joystick )
2016-11-11 01:19:34 +00:00
{
Uint16 vendor ;
SDL_JoystickGUID guid = SDL_JoystickGetGUID ( joystick ) ;
2017-01-27 13:59:58 +00:00
SDL_GetJoystickGUIDInfo ( guid , & vendor , NULL , NULL ) ;
2016-11-11 01:19:34 +00:00
return vendor ;
}
2020-11-17 01:36:47 +00:00
Uint16 SDL_JoystickGetProduct ( SDL_Joystick * joystick )
2016-11-11 01:19:34 +00:00
{
Uint16 product ;
SDL_JoystickGUID guid = SDL_JoystickGetGUID ( joystick ) ;
2017-01-27 13:59:58 +00:00
SDL_GetJoystickGUIDInfo ( guid , NULL , & product , NULL ) ;
2016-11-11 01:19:34 +00:00
return product ;
}
2020-11-17 01:36:47 +00:00
Uint16 SDL_JoystickGetProductVersion ( SDL_Joystick * joystick )
2016-11-11 01:19:34 +00:00
{
Uint16 version ;
SDL_JoystickGUID guid = SDL_JoystickGetGUID ( joystick ) ;
2017-01-27 13:59:58 +00:00
SDL_GetJoystickGUIDInfo ( guid , NULL , NULL , & version ) ;
2016-11-11 01:19:34 +00:00
return version ;
}
2020-11-17 01:36:47 +00:00
const char * SDL_JoystickGetSerial ( SDL_Joystick * joystick )
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
return NULL ;
}
return joystick - > serial ;
}
SDL_JoystickType SDL_JoystickGetType ( SDL_Joystick * joystick )
2017-01-27 13:59:58 +00:00
{
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 15:33:46 +00: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-09-30 22:39:30 +00:00
/* update the power level for this joystick */
2020-11-17 01:36:47 +00:00
void SDL_PrivateJoystickBatteryLevel ( SDL_Joystick * joystick , SDL_JoystickPowerLevel ePowerLevel )
2015-09-30 22:39:30 +00:00
{
joystick - > epowerlevel = ePowerLevel ;
}
/* return its power level */
2020-11-17 01:36:47 +00:00
SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel ( SDL_Joystick * joystick )
2015-09-30 22:39:30 +00:00
{
if ( ! SDL_PrivateJoystickValid ( joystick ) ) {
2018-08-09 23:00:17 +00:00
return SDL_JOYSTICK_POWER_UNKNOWN ;
2015-09-30 22:39:30 +00:00
}
return joystick - > epowerlevel ;
}
2020-11-14 02:01:29 +00:00
int SDL_PrivateJoystickTouchpad ( SDL_Joystick * joystick , int touchpad , int finger , Uint8 state , float x , float y , float pressure )
{
SDL_JoystickTouchpadInfo * touchpad_info ;
SDL_JoystickTouchpadFingerInfo * finger_info ;
int posted ;
2020-11-17 18:30:20 +00:00
# if !SDL_EVENTS_DISABLED
2020-11-14 02:01:29 +00:00
Uint32 event_type ;
# endif
if ( touchpad < 0 | | touchpad > = joystick - > ntouchpads ) {
return 0 ;
}
touchpad_info = & joystick - > touchpads [ touchpad ] ;
if ( finger < 0 | | finger > = touchpad_info - > nfingers ) {
return 0 ;
}
finger_info = & touchpad_info - > fingers [ finger ] ;
if ( ! state ) {
2020-11-16 23:10:02 +00:00
if ( x = = 0.0f & & y = = 0.0f ) {
2020-11-14 02:01:29 +00:00
x = finger_info - > x ;
y = finger_info - > y ;
}
pressure = 0.0f ;
}
if ( x < 0.0f ) {
x = 0.0f ;
} else if ( x > 1.0f ) {
x = 1.0f ;
}
if ( y < 0.0f ) {
y = 0.0f ;
} else if ( y > 1.0f ) {
y = 1.0f ;
}
if ( pressure < 0.0f ) {
pressure = 0.0f ;
} else if ( pressure > 1.0f ) {
pressure = 1.0f ;
}
if ( state = = finger_info - > state ) {
if ( ! state | |
( x = = finger_info - > x & & y = = finger_info - > y & & pressure = = finger_info - > pressure ) ) {
return 0 ;
}
}
# if !SDL_EVENTS_DISABLED
if ( state = = finger_info - > state ) {
event_type = SDL_CONTROLLERTOUCHPADMOTION ;
} else if ( state ) {
event_type = SDL_CONTROLLERTOUCHPADDOWN ;
} else {
event_type = SDL_CONTROLLERTOUCHPADUP ;
}
# endif
/* Update internal joystick state */
finger_info - > state = state ;
finger_info - > x = x ;
finger_info - > y = y ;
finger_info - > pressure = pressure ;
/* Post the event, if desired */
posted = 0 ;
# if !SDL_EVENTS_DISABLED
if ( SDL_GetEventState ( event_type ) = = SDL_ENABLE ) {
SDL_Event event ;
event . type = event_type ;
event . ctouchpad . which = joystick - > instance_id ;
event . ctouchpad . touchpad = touchpad ;
event . ctouchpad . finger = finger ;
event . ctouchpad . x = x ;
event . ctouchpad . y = y ;
event . ctouchpad . pressure = pressure ;
posted = SDL_PushEvent ( & event ) = = 1 ;
}
# endif /* !SDL_EVENTS_DISABLED */
return posted ;
}
2020-11-17 18:30:20 +00:00
int SDL_PrivateJoystickSensor ( SDL_Joystick * joystick , SDL_SensorType type , const float * data , int num_values )
{
int i ;
int posted = 0 ;
for ( i = 0 ; i < joystick - > nsensors ; + + i ) {
SDL_JoystickSensorInfo * sensor = & joystick - > sensors [ i ] ;
if ( sensor - > type = = type ) {
if ( sensor - > enabled ) {
num_values = SDL_min ( num_values , SDL_arraysize ( sensor - > data ) ) ;
2020-11-18 06:09:52 +00:00
if ( SDL_memcmp ( data , sensor - > data , num_values * sizeof ( * data ) ) ! = 0 ) {
/* Update internal sensor state */
SDL_memcpy ( sensor - > data , data , num_values * sizeof ( * data ) ) ;
2020-11-17 18:30:20 +00:00
2020-11-18 06:09:52 +00:00
/* Post the event, if desired */
2020-11-17 18:30:20 +00:00
# if !SDL_EVENTS_DISABLED
2020-11-18 06:09:52 +00:00
if ( SDL_GetEventState ( SDL_CONTROLLERSENSORUPDATE ) = = SDL_ENABLE ) {
SDL_Event event ;
event . type = SDL_CONTROLLERSENSORUPDATE ;
event . csensor . which = joystick - > instance_id ;
event . csensor . sensor = type ;
num_values = SDL_min ( num_values , SDL_arraysize ( event . csensor . data ) ) ;
SDL_memset ( event . csensor . data , 0 , sizeof ( event . csensor . data ) ) ;
SDL_memcpy ( event . csensor . data , data , num_values * sizeof ( * data ) ) ;
posted = SDL_PushEvent ( & event ) = = 1 ;
}
2020-11-17 18:30:20 +00:00
# endif /* !SDL_EVENTS_DISABLED */
2020-11-18 06:09:52 +00:00
}
2020-11-17 18:30:20 +00:00
}
break ;
}
}
return posted ;
}
2015-06-21 15:33:46 +00:00
/* vi: set ts=4 sw=4 expandtab: */