mirror of
https://github.com/encounter/SDL.git
synced 2025-12-12 06:45:10 +00:00
Fixes #2022, do not resume on Android when surfaceChanged
If the app is in landscape mode and the user presses the power button, a pause is followed immediately by a surfaceChanged event because the lock screen is shown in portrait mode. This triggers a "false" resume. So, we just pause and resume following the onWindowFocusChanged events. Also, wait for SDL_APP_WILLENTERBACKGROUND and SDL_APP_DIDENTERBACKGROUND before blocking the event pump.
This commit is contained in:
1249
src/joystick/SDL_gamecontroller.c
Normal file
1249
src/joystick/SDL_gamecontroller.c
Normal file
File diff suppressed because it is too large
Load Diff
65
src/joystick/SDL_gamecontrollerdb.h
Normal file
65
src/joystick/SDL_gamecontrollerdb.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
|
||||
/* Default mappings we support
|
||||
|
||||
The easiest way to generate a new mapping is to start Steam in Big Picture
|
||||
mode, configure your joystick and then look in config/config.vdf in your
|
||||
Steam installation directory for the "SDL_GamepadBind" entry.
|
||||
*/
|
||||
static const char *s_ControllerMappings [] =
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_DINPUT
|
||||
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
"88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,",
|
||||
"4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
|
||||
"xinput,X360 Controller,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,",
|
||||
#elif defined(__MACOSX__)
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
|
||||
"6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
|
||||
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
|
||||
#elif defined(__LINUX__)
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
|
||||
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
858
src/joystick/SDL_joystick.c
Normal file
858
src/joystick/SDL_joystick.c
Normal file
@@ -0,0 +1,858 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* This is the joystick API for Simple DirectMedia Layer */
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_sysjoystick.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
|
||||
static SDL_Joystick *SDL_joysticks = NULL;
|
||||
static SDL_Joystick *SDL_updating_joystick = NULL;
|
||||
|
||||
static void
|
||||
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)
|
||||
{
|
||||
int status;
|
||||
|
||||
/* 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 */
|
||||
|
||||
status = SDL_SYS_JoystickInit();
|
||||
if (status >= 0) {
|
||||
status = 0;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the number of joysticks attached to the system
|
||||
*/
|
||||
int
|
||||
SDL_NumJoysticks(void)
|
||||
{
|
||||
return SDL_SYS_NumJoysticks();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the implementation dependent name of a joystick
|
||||
*/
|
||||
const char *
|
||||
SDL_JoystickNameForIndex(int device_index)
|
||||
{
|
||||
if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
|
||||
SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
|
||||
return (NULL);
|
||||
}
|
||||
return (SDL_SYS_JoystickNameForDeviceIndex(device_index));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
SDL_Joystick *joystick;
|
||||
SDL_Joystick *joysticklist;
|
||||
const char *joystickname = NULL;
|
||||
|
||||
if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
|
||||
SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
joysticklist = SDL_joysticks;
|
||||
/* If the joystick is already open, return it
|
||||
* it is important that we have a single joystick * for each instance id
|
||||
*/
|
||||
while ( joysticklist )
|
||||
{
|
||||
if ( SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id ) {
|
||||
joystick = joysticklist;
|
||||
++joystick->ref_count;
|
||||
return (joystick);
|
||||
}
|
||||
joysticklist = joysticklist->next;
|
||||
}
|
||||
|
||||
/* Create and initialize the joystick */
|
||||
joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
|
||||
if (joystick == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_memset(joystick, 0, (sizeof *joystick));
|
||||
if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
|
||||
SDL_free(joystick);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
joystickname = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
if ( joystickname )
|
||||
joystick->name = SDL_strdup( joystickname );
|
||||
else
|
||||
joystick->name = NULL;
|
||||
|
||||
if (joystick->naxes > 0) {
|
||||
joystick->axes = (Sint16 *) SDL_malloc
|
||||
(joystick->naxes * sizeof(Sint16));
|
||||
}
|
||||
if (joystick->nhats > 0) {
|
||||
joystick->hats = (Uint8 *) SDL_malloc
|
||||
(joystick->nhats * sizeof(Uint8));
|
||||
}
|
||||
if (joystick->nballs > 0) {
|
||||
joystick->balls = (struct balldelta *) SDL_malloc
|
||||
(joystick->nballs * sizeof(*joystick->balls));
|
||||
}
|
||||
if (joystick->nbuttons > 0) {
|
||||
joystick->buttons = (Uint8 *) SDL_malloc
|
||||
(joystick->nbuttons * sizeof(Uint8));
|
||||
}
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
if (joystick->axes) {
|
||||
SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
|
||||
}
|
||||
if (joystick->hats) {
|
||||
SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
|
||||
}
|
||||
if (joystick->balls) {
|
||||
SDL_memset(joystick->balls, 0,
|
||||
joystick->nballs * sizeof(*joystick->balls));
|
||||
}
|
||||
if (joystick->buttons) {
|
||||
SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
|
||||
}
|
||||
|
||||
/* Add joystick to list */
|
||||
++joystick->ref_count;
|
||||
/* Link the joystick in the list */
|
||||
joystick->next = SDL_joysticks;
|
||||
SDL_joysticks = joystick;
|
||||
|
||||
SDL_SYS_JoystickUpdate( joystick );
|
||||
|
||||
return (joystick);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Checks to make sure the joystick is valid.
|
||||
*/
|
||||
int
|
||||
SDL_PrivateJoystickValid(SDL_Joystick * joystick)
|
||||
{
|
||||
int valid;
|
||||
|
||||
if ( joystick == NULL ) {
|
||||
SDL_SetError("Joystick hasn't been opened yet");
|
||||
valid = 0;
|
||||
} else {
|
||||
valid = 1;
|
||||
}
|
||||
|
||||
if ( joystick && joystick->closed )
|
||||
{
|
||||
valid = 0;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the number of multi-dimensional axis controls on a joystick
|
||||
*/
|
||||
int
|
||||
SDL_JoystickNumAxes(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (-1);
|
||||
}
|
||||
return (joystick->naxes);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the number of hats on a joystick
|
||||
*/
|
||||
int
|
||||
SDL_JoystickNumHats(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (-1);
|
||||
}
|
||||
return (joystick->nhats);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the number of trackballs on a joystick
|
||||
*/
|
||||
int
|
||||
SDL_JoystickNumBalls(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (-1);
|
||||
}
|
||||
return (joystick->nballs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the number of buttons on a joystick
|
||||
*/
|
||||
int
|
||||
SDL_JoystickNumButtons(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (-1);
|
||||
}
|
||||
return (joystick->nbuttons);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current state of an axis control on a joystick
|
||||
*/
|
||||
Sint16
|
||||
SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
|
||||
{
|
||||
Sint16 state;
|
||||
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (0);
|
||||
}
|
||||
if (axis < joystick->naxes) {
|
||||
state = joystick->axes[axis];
|
||||
} else {
|
||||
SDL_SetError("Joystick only has %d axes", joystick->naxes);
|
||||
state = 0;
|
||||
}
|
||||
return (state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current state of a hat on a joystick
|
||||
*/
|
||||
Uint8
|
||||
SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
|
||||
{
|
||||
Uint8 state;
|
||||
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (0);
|
||||
}
|
||||
if (hat < joystick->nhats) {
|
||||
state = joystick->hats[hat];
|
||||
} else {
|
||||
SDL_SetError("Joystick only has %d hats", joystick->nhats);
|
||||
state = 0;
|
||||
}
|
||||
return (state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the ball axis change since the last poll
|
||||
*/
|
||||
int
|
||||
SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current state of a button on a joystick
|
||||
*/
|
||||
Uint8
|
||||
SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
|
||||
{
|
||||
Uint8 state;
|
||||
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (0);
|
||||
}
|
||||
if (button < joystick->nbuttons) {
|
||||
state = joystick->buttons[button];
|
||||
} else {
|
||||
SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
|
||||
state = 0;
|
||||
}
|
||||
return (state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return if the joystick in question is currently attached to the system,
|
||||
* \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
|
||||
*/
|
||||
SDL_bool
|
||||
SDL_JoystickGetAttached(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_SYS_JoystickAttached(joystick);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the instance id for this opened joystick
|
||||
*/
|
||||
SDL_JoystickID
|
||||
SDL_JoystickInstanceID(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (joystick->instance_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the friendly name of this joystick
|
||||
*/
|
||||
const char *
|
||||
SDL_JoystickName(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (joystick->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a joystick previously opened with SDL_JoystickOpen()
|
||||
*/
|
||||
void
|
||||
SDL_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_Joystick *joysticklist;
|
||||
SDL_Joystick *joysticklistprev;
|
||||
|
||||
if (!joystick) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* First decrement ref count */
|
||||
if (--joystick->ref_count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (joystick == SDL_updating_joystick) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SYS_JoystickClose(joystick);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (joystick->name)
|
||||
SDL_free(joystick->name);
|
||||
|
||||
/* Free the data associated with this joystick */
|
||||
if (joystick->axes) {
|
||||
SDL_free(joystick->axes);
|
||||
}
|
||||
if (joystick->hats) {
|
||||
SDL_free(joystick->hats);
|
||||
}
|
||||
if (joystick->balls) {
|
||||
SDL_free(joystick->balls);
|
||||
}
|
||||
if (joystick->buttons) {
|
||||
SDL_free(joystick->buttons);
|
||||
}
|
||||
SDL_free(joystick);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_JoystickQuit(void)
|
||||
{
|
||||
/* Make sure we're not getting called in the middle of updating joysticks */
|
||||
SDL_assert(!SDL_updating_joystick);
|
||||
|
||||
/* Stop the event polling */
|
||||
while ( SDL_joysticks )
|
||||
{
|
||||
SDL_joysticks->ref_count = 1;
|
||||
SDL_JoystickClose(SDL_joysticks);
|
||||
}
|
||||
|
||||
/* Quit the joystick setup */
|
||||
SDL_SYS_JoystickQuit();
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static SDL_bool
|
||||
SDL_PrivateJoystickShouldIgnoreEvent()
|
||||
{
|
||||
if (SDL_joystick_allows_background_events)
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO)) {
|
||||
if (SDL_GetKeyboardFocus() == NULL) {
|
||||
// Video is initialized and we don't have focus, ignore the event.
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Video subsystem wasn't initialized, always allow the event
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* These are global for SDL_sysjoystick.c and SDL_events.c */
|
||||
|
||||
int
|
||||
SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
|
||||
{
|
||||
int posted;
|
||||
|
||||
/* Make sure we're not getting garbage events */
|
||||
if (axis >= joystick->naxes) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
if (value == joystick->axes[axis]) {
|
||||
return 0;
|
||||
}
|
||||
joystick->axes[axis] = value;
|
||||
|
||||
/* We ignore events if we don't have keyboard focus, except for centering
|
||||
* events.
|
||||
*/
|
||||
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
if (!(joystick->closed && joystick->uncentered)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
return (posted);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
|
||||
{
|
||||
int posted;
|
||||
|
||||
/* Make sure we're not getting garbage events */
|
||||
if (hat >= joystick->nhats) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
joystick->hats[hat] = value;
|
||||
|
||||
/* We ignore events if we don't have keyboard focus, except for centering
|
||||
* events.
|
||||
*/
|
||||
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
if (!(joystick->closed && joystick->uncentered)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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 */
|
||||
return (posted);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
|
||||
Sint16 xrel, Sint16 yrel)
|
||||
{
|
||||
int posted;
|
||||
|
||||
/* Make sure we're not getting garbage events */
|
||||
if (ball >= joystick->nballs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We ignore events if we don't have keyboard focus. */
|
||||
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal mouse state */
|
||||
joystick->balls[ball].dx += xrel;
|
||||
joystick->balls[ball].dy += yrel;
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.jball.type = SDL_JOYBALLMOTION;
|
||||
event.jball.which = joystick->instance_id;
|
||||
event.jball.ball = ball;
|
||||
event.jball.xrel = xrel;
|
||||
event.jball.yrel = yrel;
|
||||
posted = SDL_PushEvent(&event) == 1;
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
return (posted);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
|
||||
{
|
||||
int posted;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
|
||||
switch (state) {
|
||||
case SDL_PRESSED:
|
||||
event.type = SDL_JOYBUTTONDOWN;
|
||||
break;
|
||||
case SDL_RELEASED:
|
||||
event.type = SDL_JOYBUTTONUP;
|
||||
break;
|
||||
default:
|
||||
/* Invalid state -- bail */
|
||||
return (0);
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
/* Make sure we're not getting garbage events */
|
||||
if (button >= joystick->nbuttons) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We ignore events if we don't have keyboard focus, except for button
|
||||
* release. */
|
||||
if (state == SDL_PRESSED && SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
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 */
|
||||
return (posted);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_JoystickUpdate(void)
|
||||
{
|
||||
SDL_Joystick *joystick;
|
||||
|
||||
joystick = SDL_joysticks;
|
||||
while ( joystick )
|
||||
{
|
||||
SDL_Joystick *joysticknext;
|
||||
/* save off the next pointer, the Update call may cause a joystick removed event
|
||||
* and cause our joystick pointer to be freed
|
||||
*/
|
||||
joysticknext = joystick->next;
|
||||
|
||||
SDL_updating_joystick = joystick;
|
||||
|
||||
SDL_SYS_JoystickUpdate( joystick );
|
||||
|
||||
if ( joystick->closed && joystick->uncentered )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Tell the app that everything is centered/unpressed... */
|
||||
for (i = 0; i < joystick->naxes; i++)
|
||||
SDL_PrivateJoystickAxis(joystick, i, 0);
|
||||
|
||||
for (i = 0; i < joystick->nbuttons; i++)
|
||||
SDL_PrivateJoystickButton(joystick, i, 0);
|
||||
|
||||
for (i = 0; i < joystick->nhats; i++)
|
||||
SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
|
||||
|
||||
joystick->uncentered = 0;
|
||||
}
|
||||
|
||||
SDL_updating_joystick = NULL;
|
||||
|
||||
/* If the joystick was closed while updating, free it here */
|
||||
if ( joystick->ref_count <= 0 ) {
|
||||
SDL_JoystickClose(joystick);
|
||||
}
|
||||
|
||||
joystick = joysticknext;
|
||||
}
|
||||
|
||||
/* this needs to happen AFTER walking the joystick list above, so that any
|
||||
dangling hardware data from removed devices can be free'd
|
||||
*/
|
||||
SDL_SYS_JoystickDetect();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return (state);
|
||||
#endif /* SDL_EVENTS_DISABLED */
|
||||
}
|
||||
|
||||
/* return 1 if you want to run the joystick update loop this frame, used by hotplug support */
|
||||
SDL_bool
|
||||
SDL_PrivateJoystickNeedsPolling()
|
||||
{
|
||||
if (SDL_joysticks != NULL) {
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_SYS_JoystickNeedsPolling();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* return the guid for this index */
|
||||
SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
|
||||
{
|
||||
if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
|
||||
SDL_JoystickGUID emptyGUID;
|
||||
SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
|
||||
SDL_zero( emptyGUID );
|
||||
return emptyGUID;
|
||||
}
|
||||
return SDL_SYS_JoystickGetDeviceGUID( device_index );
|
||||
}
|
||||
|
||||
/* return the guid for this opened device */
|
||||
SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
return SDL_SYS_JoystickGetGUID( joystick );
|
||||
}
|
||||
|
||||
/* 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); 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);
|
||||
int len = SDL_strlen( pchGUID );
|
||||
Uint8 *p;
|
||||
int 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;
|
||||
}
|
||||
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
51
src/joystick/SDL_joystick_c.h
Normal file
51
src/joystick/SDL_joystick_c.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Useful functions and variables from SDL_joystick.c */
|
||||
#include "SDL_joystick.h"
|
||||
|
||||
/* Initialization and shutdown functions */
|
||||
extern int SDL_JoystickInit(void);
|
||||
extern void SDL_JoystickQuit(void);
|
||||
|
||||
/* Initialization and shutdown functions */
|
||||
extern int SDL_GameControllerInit(void);
|
||||
extern void SDL_GameControllerQuit(void);
|
||||
|
||||
|
||||
/* Internal event queueing functions */
|
||||
extern int SDL_PrivateJoystickAxis(SDL_Joystick * joystick,
|
||||
Uint8 axis, Sint16 value);
|
||||
extern int SDL_PrivateJoystickBall(SDL_Joystick * joystick,
|
||||
Uint8 ball, Sint16 xrel, Sint16 yrel);
|
||||
extern int SDL_PrivateJoystickHat(SDL_Joystick * joystick,
|
||||
Uint8 hat, Uint8 value);
|
||||
extern int SDL_PrivateJoystickButton(SDL_Joystick * joystick,
|
||||
Uint8 button, Uint8 state);
|
||||
|
||||
/* Helper function to let lower sys layer tell the event system if the joystick code needs to think */
|
||||
extern SDL_bool SDL_PrivateJoystickNeedsPolling();
|
||||
|
||||
/* Internal sanity checking functions */
|
||||
extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
116
src/joystick/SDL_sysjoystick.h
Normal file
116
src/joystick/SDL_sysjoystick.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* This is the system specific header for the SDL joystick API */
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_joystick_c.h"
|
||||
|
||||
/* The SDL joystick structure */
|
||||
struct _SDL_Joystick
|
||||
{
|
||||
SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */
|
||||
char *name; /* Joystick name - system dependent */
|
||||
|
||||
int naxes; /* Number of axis controls on the joystick */
|
||||
Sint16 *axes; /* Current axis states */
|
||||
|
||||
int nhats; /* Number of hats on the joystick */
|
||||
Uint8 *hats; /* Current hat states */
|
||||
|
||||
int nballs; /* Number of trackballs on the joystick */
|
||||
struct balldelta {
|
||||
int dx;
|
||||
int dy;
|
||||
} *balls; /* Current ball motion deltas */
|
||||
|
||||
int nbuttons; /* Number of buttons on the joystick */
|
||||
Uint8 *buttons; /* Current button states */
|
||||
|
||||
struct joystick_hwdata *hwdata; /* Driver dependent information */
|
||||
|
||||
int ref_count; /* Reference count for multiple opens */
|
||||
|
||||
Uint8 closed; /* 1 if this device is no longer valid */
|
||||
Uint8 uncentered; /* 1 if this device needs to have its state reset to 0 */
|
||||
struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
|
||||
};
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
* This function should return the number of available joysticks, or -1
|
||||
* on an unrecoverable fatal error.
|
||||
*/
|
||||
extern int SDL_SYS_JoystickInit(void);
|
||||
|
||||
/* Function to return the number of joystick devices plugged in right now */
|
||||
extern int SDL_SYS_NumJoysticks();
|
||||
|
||||
/* Function to cause any queued joystick insertions to be processed */
|
||||
extern void SDL_SYS_JoystickDetect();
|
||||
|
||||
/* Function to determine if the joystick loop needs to run right now */
|
||||
extern SDL_bool SDL_SYS_JoystickNeedsPolling();
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
extern const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index);
|
||||
|
||||
/* Function to get the current instance id of the joystick located at device_index */
|
||||
extern SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index);
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index);
|
||||
|
||||
/* Function to query if the joystick is currently attached
|
||||
* It returns 1 if attached, 0 otherwise.
|
||||
*/
|
||||
extern SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick);
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
extern void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick);
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
extern void SDL_SYS_JoystickClose(SDL_Joystick * joystick);
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
extern void SDL_SYS_JoystickQuit(void);
|
||||
|
||||
/* Function to return the stable GUID for a plugged in device */
|
||||
extern SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index);
|
||||
|
||||
/* Function to return the stable GUID for a opened joystick */
|
||||
extern SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick);
|
||||
|
||||
#ifdef SDL_JOYSTICK_DINPUT
|
||||
/* Function to get the current instance id of the joystick located at device_index */
|
||||
extern SDL_bool SDL_SYS_IsXInputDeviceIndex( int device_index );
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
156
src/joystick/android/SDL_sysjoystick.c
Normal file
156
src/joystick/android/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
|
||||
/* This is the system specific header for the SDL joystick API */
|
||||
#include <stdio.h> /* For the definition of NULL */
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
static const char *accelerometerName = "Android accelerometer";
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return accelerometerName;
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
if (device_index == 0) {
|
||||
joystick->nbuttons = 0;
|
||||
joystick->nhats = 0;
|
||||
joystick->nballs = 0;
|
||||
joystick->naxes = 3;
|
||||
return 0;
|
||||
} else {
|
||||
SDL_SetError("No joystick available with that index");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
int i;
|
||||
Sint16 value;
|
||||
float values[3];
|
||||
|
||||
if (Android_JNI_GetAccelerometerValues(values)) {
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
value = (Sint16)(values[i] * 32767.0f);
|
||||
SDL_PrivateJoystickAxis(joystick, i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_ANDROID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
284
src/joystick/beos/SDL_bejoystick.cc
Normal file
284
src/joystick/beos/SDL_bejoystick.cc
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_BEOS
|
||||
|
||||
/* This is the system specific header for the SDL joystick API */
|
||||
|
||||
#include <be/support/String.h>
|
||||
#include <be/device/Joystick.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
|
||||
/* The maximum number of joysticks we'll detect */
|
||||
#define MAX_JOYSTICKS 16
|
||||
|
||||
/* A list of available joysticks */
|
||||
static char *SDL_joyport[MAX_JOYSTICKS];
|
||||
static char *SDL_joyname[MAX_JOYSTICKS];
|
||||
|
||||
/* The private structure used to keep track of a joystick */
|
||||
struct joystick_hwdata
|
||||
{
|
||||
BJoystick *stick;
|
||||
uint8 *new_hats;
|
||||
int16 *new_axes;
|
||||
};
|
||||
|
||||
static int SDL_SYS_numjoysticks = 0;
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
BJoystick joystick;
|
||||
int i;
|
||||
int32 nports;
|
||||
char name[B_OS_NAME_LENGTH];
|
||||
|
||||
/* Search for attached joysticks */
|
||||
nports = joystick.CountDevices();
|
||||
SDL_SYS_numjoysticks = 0;
|
||||
SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport));
|
||||
SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname));
|
||||
for (i = 0; (SDL_SYS_numjoysticks < MAX_JOYSTICKS) && (i < nports); ++i)
|
||||
{
|
||||
if (joystick.GetDeviceName(i, name) == B_OK) {
|
||||
if (joystick.Open(name) != B_ERROR) {
|
||||
BString stick_name;
|
||||
joystick.GetControllerName(&stick_name);
|
||||
SDL_joyport[SDL_SYS_numjoysticks] = strdup(name);
|
||||
SDL_joyname[SDL_SYS_numjoysticks] = strdup(stick_name.String());
|
||||
SDL_SYS_numjoysticks++;
|
||||
joystick.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (SDL_SYS_numjoysticks);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return SDL_SYS_numjoysticks;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return SDL_joyname[device_index];
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
BJoystick *stick;
|
||||
|
||||
/* Create the joystick data structure */
|
||||
joystick->instance_id = device_index;
|
||||
joystick->hwdata = (struct joystick_hwdata *)
|
||||
SDL_malloc(sizeof(*joystick->hwdata));
|
||||
if (joystick->hwdata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
|
||||
stick = new BJoystick;
|
||||
joystick->hwdata->stick = stick;
|
||||
|
||||
/* Open the requested joystick for use */
|
||||
if (stick->Open(SDL_joyport[device_index]) == B_ERROR) {
|
||||
SDL_SYS_JoystickClose(joystick);
|
||||
return SDL_SetError("Unable to open joystick");
|
||||
}
|
||||
|
||||
/* Set the joystick to calibrated mode */
|
||||
stick->EnableCalibration();
|
||||
|
||||
/* Get the number of buttons, hats, and axes on the joystick */
|
||||
joystick->nbuttons = stick->CountButtons();
|
||||
joystick->naxes = stick->CountAxes();
|
||||
joystick->nhats = stick->CountHats();
|
||||
|
||||
joystick->hwdata->new_axes = (int16 *)
|
||||
SDL_malloc(joystick->naxes * sizeof(int16));
|
||||
joystick->hwdata->new_hats = (uint8 *)
|
||||
SDL_malloc(joystick->nhats * sizeof(uint8));
|
||||
if (!joystick->hwdata->new_hats || !joystick->hwdata->new_axes) {
|
||||
SDL_SYS_JoystickClose(joystick);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
/* We're done! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
static const Uint8 hat_map[9] = {
|
||||
SDL_HAT_CENTERED,
|
||||
SDL_HAT_UP,
|
||||
SDL_HAT_RIGHTUP,
|
||||
SDL_HAT_RIGHT,
|
||||
SDL_HAT_RIGHTDOWN,
|
||||
SDL_HAT_DOWN,
|
||||
SDL_HAT_LEFTDOWN,
|
||||
SDL_HAT_LEFT,
|
||||
SDL_HAT_LEFTUP
|
||||
};
|
||||
const int JITTER = (32768 / 10); /* 10% jitter threshold (ok?) */
|
||||
|
||||
BJoystick *stick;
|
||||
int i, change;
|
||||
int16 *axes;
|
||||
uint8 *hats;
|
||||
uint32 buttons;
|
||||
|
||||
/* Set up data pointers */
|
||||
stick = joystick->hwdata->stick;
|
||||
axes = joystick->hwdata->new_axes;
|
||||
hats = joystick->hwdata->new_hats;
|
||||
|
||||
/* Get the new joystick state */
|
||||
stick->Update();
|
||||
stick->GetAxisValues(axes);
|
||||
stick->GetHatValues(hats);
|
||||
buttons = stick->ButtonValues();
|
||||
|
||||
/* Generate axis motion events */
|
||||
for (i = 0; i < joystick->naxes; ++i) {
|
||||
change = ((int32) axes[i] - joystick->axes[i]);
|
||||
if ((change > JITTER) || (change < -JITTER)) {
|
||||
SDL_PrivateJoystickAxis(joystick, i, axes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate hat change events */
|
||||
for (i = 0; i < joystick->nhats; ++i) {
|
||||
if (hats[i] != joystick->hats[i]) {
|
||||
SDL_PrivateJoystickHat(joystick, i, hat_map[hats[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate button events */
|
||||
for (i = 0; i < joystick->nbuttons; ++i) {
|
||||
if ((buttons & 0x01) != joystick->buttons[i]) {
|
||||
SDL_PrivateJoystickButton(joystick, i, (buttons & 0x01));
|
||||
}
|
||||
buttons >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata) {
|
||||
joystick->hwdata->stick->Close();
|
||||
delete joystick->hwdata->stick;
|
||||
if (joystick->hwdata->new_hats) {
|
||||
SDL_free(joystick->hwdata->new_hats);
|
||||
}
|
||||
if (joystick->hwdata->new_axes) {
|
||||
SDL_free(joystick->hwdata->new_axes);
|
||||
}
|
||||
SDL_free(joystick->hwdata);
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; SDL_joyport[i]; ++i) {
|
||||
SDL_free(SDL_joyport[i]);
|
||||
}
|
||||
SDL_joyport[0] = NULL;
|
||||
|
||||
for (i = 0; SDL_joyname[i]; ++i) {
|
||||
SDL_free(SDL_joyname[i]);
|
||||
}
|
||||
SDL_joyname[0] = NULL;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
}; // extern "C"
|
||||
|
||||
#endif /* SDL_JOYSTICK_BEOS */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
668
src/joystick/bsd/SDL_sysjoystick.c
Normal file
668
src/joystick/bsd/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_USBHID
|
||||
|
||||
/*
|
||||
* Joystick driver for the uhid(4) interface found in OpenBSD,
|
||||
* NetBSD and FreeBSD.
|
||||
*
|
||||
* Maintainer: <vedge at csoft.org>
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __FreeBSD_kernel_version
|
||||
#define __FreeBSD_kernel_version __FreeBSD_version
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_USB_H)
|
||||
#include <usb.h>
|
||||
#endif
|
||||
#ifdef __DragonFly__
|
||||
#include <bus/usb/usb.h>
|
||||
#include <bus/usb/usbhid.h>
|
||||
#else
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usbhid.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_USBHID_H)
|
||||
#include <usbhid.h>
|
||||
#elif defined(HAVE_LIBUSB_H)
|
||||
#include <libusb.h>
|
||||
#elif defined(HAVE_LIBUSBHID_H)
|
||||
#include <libusbhid.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FREEBSD__) || defined(__FreeBSD_kernel__)
|
||||
#ifndef __DragonFly__
|
||||
#include <osreldate.h>
|
||||
#endif
|
||||
#if __FreeBSD_kernel_version > 800063
|
||||
#include <dev/usb/usb_ioctl.h>
|
||||
#endif
|
||||
#include <sys/joystick.h>
|
||||
#endif
|
||||
|
||||
#if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
|
||||
#include <machine/joystick.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
#define MAX_UHID_JOYS 16
|
||||
#define MAX_JOY_JOYS 2
|
||||
#define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS)
|
||||
|
||||
|
||||
struct report
|
||||
{
|
||||
#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
|
||||
void *buf; /* Buffer */
|
||||
#elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
|
||||
struct usb_gen_descriptor *buf; /* Buffer */
|
||||
#else
|
||||
struct usb_ctl_report *buf; /* Buffer */
|
||||
#endif
|
||||
size_t size; /* Buffer size */
|
||||
int rid; /* Report ID */
|
||||
enum
|
||||
{
|
||||
SREPORT_UNINIT,
|
||||
SREPORT_CLEAN,
|
||||
SREPORT_DIRTY
|
||||
} status;
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
int uhid_report;
|
||||
hid_kind_t kind;
|
||||
const char *name;
|
||||
} const repinfo[] = {
|
||||
{UHID_INPUT_REPORT, hid_input, "input"},
|
||||
{UHID_OUTPUT_REPORT, hid_output, "output"},
|
||||
{UHID_FEATURE_REPORT, hid_feature, "feature"}
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
REPORT_INPUT = 0,
|
||||
REPORT_OUTPUT = 1,
|
||||
REPORT_FEATURE = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
JOYAXE_X,
|
||||
JOYAXE_Y,
|
||||
JOYAXE_Z,
|
||||
JOYAXE_SLIDER,
|
||||
JOYAXE_WHEEL,
|
||||
JOYAXE_RX,
|
||||
JOYAXE_RY,
|
||||
JOYAXE_RZ,
|
||||
JOYAXE_count
|
||||
};
|
||||
|
||||
struct joystick_hwdata
|
||||
{
|
||||
int fd;
|
||||
char *path;
|
||||
enum
|
||||
{
|
||||
BSDJOY_UHID, /* uhid(4) */
|
||||
BSDJOY_JOY /* joy(4) */
|
||||
} type;
|
||||
struct report_desc *repdesc;
|
||||
struct report inreport;
|
||||
int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,.. */
|
||||
};
|
||||
|
||||
static char *joynames[MAX_JOYS];
|
||||
static char *joydevnames[MAX_JOYS];
|
||||
|
||||
static int report_alloc(struct report *, struct report_desc *, int);
|
||||
static void report_free(struct report *);
|
||||
|
||||
#if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063)
|
||||
#define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
|
||||
#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000))
|
||||
#define REP_BUF_DATA(rep) ((rep)->buf)
|
||||
#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063))
|
||||
#define REP_BUF_DATA(rep) ((rep)->buf->ugd_data)
|
||||
#else
|
||||
#define REP_BUF_DATA(rep) ((rep)->buf->data)
|
||||
#endif
|
||||
|
||||
static int SDL_SYS_numjoysticks = 0;
|
||||
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
char s[16];
|
||||
int i, fd;
|
||||
|
||||
SDL_SYS_numjoysticks = 0;
|
||||
|
||||
SDL_memset(joynames, 0, sizeof(joynames));
|
||||
SDL_memset(joydevnames, 0, sizeof(joydevnames));
|
||||
|
||||
for (i = 0; i < MAX_UHID_JOYS; i++) {
|
||||
SDL_Joystick nj;
|
||||
|
||||
SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
|
||||
|
||||
joynames[SDL_SYS_numjoysticks] = strdup(s);
|
||||
|
||||
if (SDL_SYS_JoystickOpen(&nj, SDL_SYS_numjoysticks) == 0) {
|
||||
SDL_SYS_JoystickClose(&nj);
|
||||
SDL_SYS_numjoysticks++;
|
||||
} else {
|
||||
SDL_free(joynames[SDL_SYS_numjoysticks]);
|
||||
joynames[SDL_SYS_numjoysticks] = NULL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAX_JOY_JOYS; i++) {
|
||||
SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
|
||||
fd = open(s, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
joynames[SDL_SYS_numjoysticks++] = strdup(s);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the default USB HID usage table. */
|
||||
hid_init(NULL);
|
||||
|
||||
return (SDL_SYS_numjoysticks);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return SDL_SYS_numjoysticks;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
if (joydevnames[device_index] != NULL) {
|
||||
return (joydevnames[device_index]);
|
||||
}
|
||||
return (joynames[device_index]);
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
static int
|
||||
usage_to_joyaxe(unsigned usage)
|
||||
{
|
||||
int joyaxe;
|
||||
switch (usage) {
|
||||
case HUG_X:
|
||||
joyaxe = JOYAXE_X;
|
||||
break;
|
||||
case HUG_Y:
|
||||
joyaxe = JOYAXE_Y;
|
||||
break;
|
||||
case HUG_Z:
|
||||
joyaxe = JOYAXE_Z;
|
||||
break;
|
||||
case HUG_SLIDER:
|
||||
joyaxe = JOYAXE_SLIDER;
|
||||
break;
|
||||
case HUG_WHEEL:
|
||||
joyaxe = JOYAXE_WHEEL;
|
||||
break;
|
||||
case HUG_RX:
|
||||
joyaxe = JOYAXE_RX;
|
||||
break;
|
||||
case HUG_RY:
|
||||
joyaxe = JOYAXE_RY;
|
||||
break;
|
||||
case HUG_RZ:
|
||||
joyaxe = JOYAXE_RZ;
|
||||
break;
|
||||
default:
|
||||
joyaxe = -1;
|
||||
}
|
||||
return joyaxe;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
hatval_to_sdl(Sint32 hatval)
|
||||
{
|
||||
static const unsigned hat_dir_map[8] = {
|
||||
SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN,
|
||||
SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP
|
||||
};
|
||||
unsigned result;
|
||||
if ((hatval & 7) == hatval)
|
||||
result = hat_dir_map[hatval];
|
||||
else
|
||||
result = SDL_HAT_CENTERED;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joy, int device_index)
|
||||
{
|
||||
char *path = joynames[device_index];
|
||||
struct joystick_hwdata *hw;
|
||||
struct hid_item hitem;
|
||||
struct hid_data *hdata;
|
||||
struct report *rep;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return SDL_SetError("%s: %s", path, strerror(errno));
|
||||
}
|
||||
|
||||
joy->instance_id = device_index;
|
||||
hw = (struct joystick_hwdata *)
|
||||
SDL_malloc(sizeof(struct joystick_hwdata));
|
||||
if (hw == NULL) {
|
||||
close(fd);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
joy->hwdata = hw;
|
||||
hw->fd = fd;
|
||||
hw->path = strdup(path);
|
||||
if (!SDL_strncmp(path, "/dev/joy", 8)) {
|
||||
hw->type = BSDJOY_JOY;
|
||||
joy->naxes = 2;
|
||||
joy->nbuttons = 2;
|
||||
joy->nhats = 0;
|
||||
joy->nballs = 0;
|
||||
joydevnames[device_index] = strdup("Gameport joystick");
|
||||
goto usbend;
|
||||
} else {
|
||||
hw->type = BSDJOY_UHID;
|
||||
}
|
||||
|
||||
{
|
||||
int ax;
|
||||
for (ax = 0; ax < JOYAXE_count; ax++)
|
||||
hw->axis_map[ax] = -1;
|
||||
}
|
||||
hw->repdesc = hid_get_report_desc(fd);
|
||||
if (hw->repdesc == NULL) {
|
||||
SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path,
|
||||
strerror(errno));
|
||||
goto usberr;
|
||||
}
|
||||
rep = &hw->inreport;
|
||||
#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__)
|
||||
rep->rid = hid_get_report_id(fd);
|
||||
if (rep->rid < 0) {
|
||||
#else
|
||||
if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
|
||||
#endif
|
||||
rep->rid = -1; /* XXX */
|
||||
}
|
||||
if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
|
||||
goto usberr;
|
||||
}
|
||||
if (rep->size <= 0) {
|
||||
SDL_SetError("%s: Input report descriptor has invalid length",
|
||||
hw->path);
|
||||
goto usberr;
|
||||
}
|
||||
#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
|
||||
hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
|
||||
#else
|
||||
hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
|
||||
#endif
|
||||
if (hdata == NULL) {
|
||||
SDL_SetError("%s: Cannot start HID parser", hw->path);
|
||||
goto usberr;
|
||||
}
|
||||
joy->naxes = 0;
|
||||
joy->nbuttons = 0;
|
||||
joy->nhats = 0;
|
||||
joy->nballs = 0;
|
||||
for (i = 0; i < JOYAXE_count; i++)
|
||||
hw->axis_map[i] = -1;
|
||||
|
||||
while (hid_get_item(hdata, &hitem) > 0) {
|
||||
char *sp;
|
||||
const char *s;
|
||||
|
||||
switch (hitem.kind) {
|
||||
case hid_collection:
|
||||
switch (HID_PAGE(hitem.usage)) {
|
||||
case HUP_GENERIC_DESKTOP:
|
||||
switch (HID_USAGE(hitem.usage)) {
|
||||
case HUG_JOYSTICK:
|
||||
case HUG_GAME_PAD:
|
||||
s = hid_usage_in_page(hitem.usage);
|
||||
sp = SDL_malloc(SDL_strlen(s) + 5);
|
||||
SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)",
|
||||
s, device_index);
|
||||
joydevnames[device_index] = sp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case hid_input:
|
||||
switch (HID_PAGE(hitem.usage)) {
|
||||
case HUP_GENERIC_DESKTOP:
|
||||
{
|
||||
unsigned usage = HID_USAGE(hitem.usage);
|
||||
int joyaxe = usage_to_joyaxe(usage);
|
||||
if (joyaxe >= 0) {
|
||||
hw->axis_map[joyaxe] = 1;
|
||||
} else if (usage == HUG_HAT_SWITCH) {
|
||||
joy->nhats++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HUP_BUTTON:
|
||||
joy->nbuttons++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
hid_end_parse(hdata);
|
||||
for (i = 0; i < JOYAXE_count; i++)
|
||||
if (hw->axis_map[i] > 0)
|
||||
hw->axis_map[i] = joy->naxes++;
|
||||
|
||||
usbend:
|
||||
/* The poll blocks the event thread. */
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
|
||||
return (0);
|
||||
usberr:
|
||||
close(hw->fd);
|
||||
SDL_free(hw->path);
|
||||
SDL_free(hw);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joy)
|
||||
{
|
||||
struct hid_item hitem;
|
||||
struct hid_data *hdata;
|
||||
struct report *rep;
|
||||
int nbutton, naxe = -1;
|
||||
Sint32 v;
|
||||
|
||||
#if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
|
||||
struct joystick gameport;
|
||||
static int x, y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
|
||||
|
||||
if (joy->hwdata->type == BSDJOY_JOY) {
|
||||
if (read(joy->hwdata->fd, &gameport, sizeof gameport) !=
|
||||
sizeof gameport)
|
||||
return;
|
||||
if (abs(x - gameport.x) > 8) {
|
||||
x = gameport.x;
|
||||
if (x < xmin) {
|
||||
xmin = x;
|
||||
}
|
||||
if (x > xmax) {
|
||||
xmax = x;
|
||||
}
|
||||
if (xmin == xmax) {
|
||||
xmin--;
|
||||
xmax++;
|
||||
}
|
||||
v = (Sint32) x;
|
||||
v -= (xmax + xmin + 1) / 2;
|
||||
v *= 32768 / ((xmax - xmin + 1) / 2);
|
||||
SDL_PrivateJoystickAxis(joy, 0, v);
|
||||
}
|
||||
if (abs(y - gameport.y) > 8) {
|
||||
y = gameport.y;
|
||||
if (y < ymin) {
|
||||
ymin = y;
|
||||
}
|
||||
if (y > ymax) {
|
||||
ymax = y;
|
||||
}
|
||||
if (ymin == ymax) {
|
||||
ymin--;
|
||||
ymax++;
|
||||
}
|
||||
v = (Sint32) y;
|
||||
v -= (ymax + ymin + 1) / 2;
|
||||
v *= 32768 / ((ymax - ymin + 1) / 2);
|
||||
SDL_PrivateJoystickAxis(joy, 1, v);
|
||||
}
|
||||
if (gameport.b1 != joy->buttons[0]) {
|
||||
SDL_PrivateJoystickButton(joy, 0, gameport.b1);
|
||||
}
|
||||
if (gameport.b2 != joy->buttons[1]) {
|
||||
SDL_PrivateJoystickButton(joy, 1, gameport.b2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
|
||||
|
||||
rep = &joy->hwdata->inreport;
|
||||
|
||||
if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) {
|
||||
return;
|
||||
}
|
||||
#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
|
||||
hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
|
||||
#else
|
||||
hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
|
||||
#endif
|
||||
if (hdata == NULL) {
|
||||
fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);
|
||||
return;
|
||||
}
|
||||
|
||||
for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
|
||||
switch (hitem.kind) {
|
||||
case hid_input:
|
||||
switch (HID_PAGE(hitem.usage)) {
|
||||
case HUP_GENERIC_DESKTOP:
|
||||
{
|
||||
unsigned usage = HID_USAGE(hitem.usage);
|
||||
int joyaxe = usage_to_joyaxe(usage);
|
||||
if (joyaxe >= 0) {
|
||||
naxe = joy->hwdata->axis_map[joyaxe];
|
||||
/* scaleaxe */
|
||||
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
|
||||
v -= (hitem.logical_maximum +
|
||||
hitem.logical_minimum + 1) / 2;
|
||||
v *= 32768 /
|
||||
((hitem.logical_maximum -
|
||||
hitem.logical_minimum + 1) / 2);
|
||||
if (v != joy->axes[naxe]) {
|
||||
SDL_PrivateJoystickAxis(joy, naxe, v);
|
||||
}
|
||||
} else if (usage == HUG_HAT_SWITCH) {
|
||||
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
|
||||
SDL_PrivateJoystickHat(joy, 0,
|
||||
hatval_to_sdl(v) -
|
||||
hitem.logical_minimum);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HUP_BUTTON:
|
||||
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
|
||||
if (joy->buttons[nbutton] != v) {
|
||||
SDL_PrivateJoystickButton(joy, nbutton, v);
|
||||
}
|
||||
nbutton++;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
hid_end_parse(hdata);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joy)
|
||||
{
|
||||
if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) {
|
||||
report_free(&joy->hwdata->inreport);
|
||||
hid_dispose_report_desc(joy->hwdata->repdesc);
|
||||
}
|
||||
close(joy->hwdata->fd);
|
||||
SDL_free(joy->hwdata->path);
|
||||
SDL_free(joy->hwdata);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_JOYS; i++) {
|
||||
if (joynames[i] != NULL)
|
||||
SDL_free(joynames[i]);
|
||||
if (joydevnames[i] != NULL)
|
||||
SDL_free(joydevnames[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
static int
|
||||
report_alloc(struct report *r, struct report_desc *rd, int repind)
|
||||
{
|
||||
int len;
|
||||
|
||||
#ifdef __DragonFly__
|
||||
len = hid_report_size(rd, r->rid, repinfo[repind].kind);
|
||||
#elif __FREEBSD__
|
||||
# if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
|
||||
# if (__FreeBSD_kernel_version <= 500111)
|
||||
len = hid_report_size(rd, r->rid, repinfo[repind].kind);
|
||||
# else
|
||||
len = hid_report_size(rd, repinfo[repind].kind, r->rid);
|
||||
# endif
|
||||
# else
|
||||
len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
|
||||
# endif
|
||||
#else
|
||||
# ifdef USBHID_NEW
|
||||
len = hid_report_size(rd, repinfo[repind].kind, r->rid);
|
||||
# else
|
||||
len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (len < 0) {
|
||||
return SDL_SetError("Negative HID report size");
|
||||
}
|
||||
r->size = len;
|
||||
|
||||
if (r->size > 0) {
|
||||
#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
|
||||
r->buf = SDL_malloc(r->size);
|
||||
#else
|
||||
r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) +
|
||||
r->size);
|
||||
#endif
|
||||
if (r->buf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
} else {
|
||||
r->buf = NULL;
|
||||
}
|
||||
|
||||
r->status = SREPORT_CLEAN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
report_free(struct report *r)
|
||||
{
|
||||
if (r->buf != NULL) {
|
||||
SDL_free(r->buf);
|
||||
}
|
||||
r->status = SREPORT_UNINIT;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_USBHID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
1155
src/joystick/darwin/SDL_sysjoystick.c
Normal file
1155
src/joystick/darwin/SDL_sysjoystick.c
Normal file
File diff suppressed because it is too large
Load Diff
90
src/joystick/darwin/SDL_sysjoystick_c.h
Normal file
90
src/joystick/darwin/SDL_sysjoystick_c.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef SDL_JOYSTICK_IOKIT_H
|
||||
|
||||
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
|
||||
struct recElement
|
||||
{
|
||||
IOHIDElementCookie cookie; /* unique value which identifies element, will NOT change */
|
||||
long usagePage, usage; /* HID usage */
|
||||
long min; /* reported min value possible */
|
||||
long max; /* reported max value possible */
|
||||
#if 0
|
||||
/* TODO: maybe should handle the following stuff somehow? */
|
||||
|
||||
long scaledMin; /* reported scaled min value possible */
|
||||
long scaledMax; /* reported scaled max value possible */
|
||||
long size; /* size in bits of data return from element */
|
||||
Boolean relative; /* are reports relative to last report (deltas) */
|
||||
Boolean wrapping; /* does element wrap around (one value higher than max is min) */
|
||||
Boolean nonLinear; /* are the values reported non-linear relative to element movement */
|
||||
Boolean preferredState; /* does element have a preferred state (such as a button) */
|
||||
Boolean nullState; /* does element have null state */
|
||||
#endif /* 0 */
|
||||
|
||||
/* runtime variables used for auto-calibration */
|
||||
long minReport; /* min returned value */
|
||||
long maxReport; /* max returned value */
|
||||
|
||||
struct recElement *pNext; /* next element in list */
|
||||
};
|
||||
typedef struct recElement recElement;
|
||||
|
||||
struct joystick_hwdata
|
||||
{
|
||||
io_service_t ffservice; /* Interface for force feedback, 0 = no ff */
|
||||
IOHIDDeviceInterface **interface; /* interface to device, NULL = no interface */
|
||||
IONotificationPortRef notificationPort; /* port to be notified on joystick removal */
|
||||
io_iterator_t portIterator; /* iterator for removal callback */
|
||||
|
||||
char product[256]; /* name of product */
|
||||
long usage; /* usage page from IOUSBHID Parser.h which defines general usage */
|
||||
long usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */
|
||||
|
||||
long axes; /* number of axis (calculated, not reported by device) */
|
||||
long buttons; /* number of buttons (calculated, not reported by device) */
|
||||
long hats; /* number of hat switches (calculated, not reported by device) */
|
||||
long elements; /* number of total elements (should be total of above) (calculated, not reported by device) */
|
||||
|
||||
recElement *firstAxis;
|
||||
recElement *firstButton;
|
||||
recElement *firstHat;
|
||||
|
||||
int removed;
|
||||
int uncentered;
|
||||
|
||||
int instance_id;
|
||||
SDL_JoystickGUID guid;
|
||||
Uint8 send_open_event; /* 1 if we need to send an Added event for this device */
|
||||
|
||||
struct joystick_hwdata *pNext; /* next device */
|
||||
};
|
||||
typedef struct joystick_hwdata recDevice;
|
||||
|
||||
|
||||
#endif /* SDL_JOYSTICK_IOKIT_H */
|
||||
133
src/joystick/dummy/SDL_sysjoystick.c
Normal file
133
src/joystick/dummy/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
|
||||
|
||||
/* This is the system specific header for the SDL joystick API */
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
SDL_SetError("Logic error: No joysticks available");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
return SDL_SetError("Logic error: No joysticks available");
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_DUMMY || SDL_JOYSTICK_DISABLED */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
44
src/joystick/iphoneos/SDLUIAccelerationDelegate.h
Normal file
44
src/joystick/iphoneos/SDLUIAccelerationDelegate.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <SDL_types.h>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
@interface SDLUIAccelerationDelegate: NSObject <UIAccelerometerDelegate> {
|
||||
|
||||
UIAccelerationValue x, y, z;
|
||||
BOOL isRunning;
|
||||
BOOL hasNewData;
|
||||
|
||||
}
|
||||
|
||||
+(SDLUIAccelerationDelegate *)sharedDelegate;
|
||||
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration;
|
||||
-(void)getLastOrientation:(Sint16 *)data;
|
||||
-(void)startup;
|
||||
-(void)shutdown;
|
||||
-(BOOL)isRunning;
|
||||
-(BOOL)hasNewData;
|
||||
-(void)setHasNewData:(BOOL)value;
|
||||
|
||||
@end
|
||||
/* *INDENT-ON* */
|
||||
141
src/joystick/iphoneos/SDLUIAccelerationDelegate.m
Normal file
141
src/joystick/iphoneos/SDLUIAccelerationDelegate.m
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#import "SDLUIAccelerationDelegate.h"
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#import "../../../include/SDL_config_iphoneos.h"
|
||||
|
||||
static SDLUIAccelerationDelegate *sharedDelegate=nil;
|
||||
|
||||
@implementation SDLUIAccelerationDelegate
|
||||
|
||||
/*
|
||||
Returns a shared instance of the SDLUIAccelerationDelegate, creating the shared delegate if it doesn't exist yet.
|
||||
*/
|
||||
+(SDLUIAccelerationDelegate *)sharedDelegate {
|
||||
if (sharedDelegate == nil) {
|
||||
sharedDelegate = [[SDLUIAccelerationDelegate alloc] init];
|
||||
}
|
||||
return sharedDelegate;
|
||||
}
|
||||
/*
|
||||
UIAccelerometerDelegate delegate method. Invoked by the UIAccelerometer instance when it has new data for us.
|
||||
We just take the data and mark that we have new data available so that the joystick system will pump it to the
|
||||
events system when SDL_SYS_JoystickUpdate is called.
|
||||
*/
|
||||
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
|
||||
|
||||
x = acceleration.x;
|
||||
y = acceleration.y;
|
||||
z = acceleration.z;
|
||||
|
||||
hasNewData = YES;
|
||||
}
|
||||
/*
|
||||
getLastOrientation -- put last obtained accelerometer data into Sint16 array
|
||||
|
||||
Called from the joystick system when it needs the accelerometer data.
|
||||
Function grabs the last data sent to the accelerometer and converts it
|
||||
from floating point to Sint16, which is what the joystick system expects.
|
||||
|
||||
To do the conversion, the data is first clamped onto the interval
|
||||
[-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
|
||||
by MAX_SINT16 so that it is mapped to the full range of an Sint16.
|
||||
|
||||
You can customize the clamped range of this function by modifying the
|
||||
SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
|
||||
|
||||
Once converted to Sint16, the accelerometer data no longer has coherent units.
|
||||
You can convert the data back to units of g-force by multiplying it
|
||||
in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
|
||||
*/
|
||||
-(void)getLastOrientation:(Sint16 *)data {
|
||||
|
||||
#define MAX_SINT16 0x7FFF
|
||||
|
||||
/* clamp the data */
|
||||
if (x > SDL_IPHONE_MAX_GFORCE) x = SDL_IPHONE_MAX_GFORCE;
|
||||
else if (x < -SDL_IPHONE_MAX_GFORCE) x = -SDL_IPHONE_MAX_GFORCE;
|
||||
if (y > SDL_IPHONE_MAX_GFORCE) y = SDL_IPHONE_MAX_GFORCE;
|
||||
else if (y < -SDL_IPHONE_MAX_GFORCE) y = -SDL_IPHONE_MAX_GFORCE;
|
||||
if (z > SDL_IPHONE_MAX_GFORCE) z = SDL_IPHONE_MAX_GFORCE;
|
||||
else if (z < -SDL_IPHONE_MAX_GFORCE) z = -SDL_IPHONE_MAX_GFORCE;
|
||||
|
||||
/* pass in data mapped to range of SInt16 */
|
||||
data[0] = (x / SDL_IPHONE_MAX_GFORCE) * MAX_SINT16;
|
||||
data[1] = (y / SDL_IPHONE_MAX_GFORCE) * MAX_SINT16;
|
||||
data[2] = (z / SDL_IPHONE_MAX_GFORCE) * MAX_SINT16;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize SDLUIAccelerationDelegate. Since we don't have any data yet,
|
||||
just set our last received data to zero, and indicate we don't have any;
|
||||
*/
|
||||
-(id)init {
|
||||
self = [super init];
|
||||
x = y = z = 0.0;
|
||||
hasNewData = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
sharedDelegate = nil;
|
||||
[self shutdown];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/*
|
||||
Lets our delegate start receiving accelerometer updates.
|
||||
*/
|
||||
-(void)startup {
|
||||
[UIAccelerometer sharedAccelerometer].delegate = self;
|
||||
isRunning = YES;
|
||||
}
|
||||
/*
|
||||
Stops our delegate from receiving accelerometer updates.
|
||||
*/
|
||||
-(void)shutdown {
|
||||
if ([UIAccelerometer sharedAccelerometer].delegate == self) {
|
||||
[UIAccelerometer sharedAccelerometer].delegate = nil;
|
||||
}
|
||||
isRunning = NO;
|
||||
}
|
||||
/*
|
||||
Our we currently receiving accelerometer updates?
|
||||
*/
|
||||
-(BOOL)isRunning {
|
||||
return isRunning;
|
||||
}
|
||||
/*
|
||||
Do we have any data that hasn't been pumped into SDL's event system?
|
||||
*/
|
||||
-(BOOL)hasNewData {
|
||||
return hasNewData;
|
||||
}
|
||||
/*
|
||||
When the joystick system grabs the new data, it sets this to NO.
|
||||
*/
|
||||
-(void)setHasNewData:(BOOL)value {
|
||||
hasNewData = value;
|
||||
}
|
||||
|
||||
@end
|
||||
153
src/joystick/iphoneos/SDL_sysjoystick.m
Normal file
153
src/joystick/iphoneos/SDL_sysjoystick.m
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* This is the system specific header for the SDL joystick API */
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#import "SDLUIAccelerationDelegate.h"
|
||||
|
||||
const char *accelerometerName = "iPhone accelerometer";
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return accelerometerName;
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
joystick->naxes = 3;
|
||||
joystick->nhats = 0;
|
||||
joystick->nballs = 0;
|
||||
joystick->nbuttons = 0;
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] startup];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
|
||||
Sint16 orientation[3];
|
||||
|
||||
if ([[SDLUIAccelerationDelegate sharedDelegate] hasNewData]) {
|
||||
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] getLastOrientation: orientation];
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] setHasNewData: NO];
|
||||
|
||||
SDL_PrivateJoystickAxis(joystick, 0, orientation[0]);
|
||||
SDL_PrivateJoystickAxis(joystick, 1, orientation[1]);
|
||||
SDL_PrivateJoystickAxis(joystick, 2, orientation[2]);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if ([[SDLUIAccelerationDelegate sharedDelegate] isRunning]) {
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] shutdown];
|
||||
}
|
||||
SDL_SetError("No joystick open with that index");
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
1038
src/joystick/linux/SDL_sysjoystick.c
Normal file
1038
src/joystick/linux/SDL_sysjoystick.c
Normal file
File diff suppressed because it is too large
Load Diff
57
src/joystick/linux/SDL_sysjoystick_c.h
Normal file
57
src/joystick/linux/SDL_sysjoystick_c.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
struct SDL_joylist_item;
|
||||
|
||||
/* The private structure used to keep track of a joystick */
|
||||
struct joystick_hwdata
|
||||
{
|
||||
int fd;
|
||||
struct SDL_joylist_item *item;
|
||||
SDL_JoystickGUID guid;
|
||||
char *fname; /* Used in haptic subsystem */
|
||||
|
||||
/* The current Linux joystick driver maps hats to two axes */
|
||||
struct hwdata_hat
|
||||
{
|
||||
int axis[2];
|
||||
} *hats;
|
||||
/* The current Linux joystick driver maps balls to two axes */
|
||||
struct hwdata_ball
|
||||
{
|
||||
int axis[2];
|
||||
} *balls;
|
||||
|
||||
/* Support for the Linux 2.4 unified input interface */
|
||||
Uint8 key_map[KEY_MAX - BTN_MISC];
|
||||
Uint8 abs_map[ABS_MAX];
|
||||
struct axis_correct
|
||||
{
|
||||
int used;
|
||||
int coef[3];
|
||||
} abs_correct[ABS_MAX];
|
||||
|
||||
int fresh;
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
274
src/joystick/psp/SDL_sysjoystick.c
Normal file
274
src/joystick/psp/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is the system specific header for the SDL joystick API */
|
||||
#include <pspctrl.h>
|
||||
#include <pspkernel.h>
|
||||
|
||||
#include <stdio.h> /* For the definition of NULL */
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
/* Current pad state */
|
||||
static SceCtrlData pad = { .Lx = 0, .Ly = 0, .Buttons = 0 };
|
||||
static SDL_sem *pad_sem = NULL;
|
||||
static SDL_Thread *thread = NULL;
|
||||
static int running = 0;
|
||||
static const enum PspCtrlButtons button_map[] = {
|
||||
PSP_CTRL_TRIANGLE, PSP_CTRL_CIRCLE, PSP_CTRL_CROSS, PSP_CTRL_SQUARE,
|
||||
PSP_CTRL_LTRIGGER, PSP_CTRL_RTRIGGER,
|
||||
PSP_CTRL_DOWN, PSP_CTRL_LEFT, PSP_CTRL_UP, PSP_CTRL_RIGHT,
|
||||
PSP_CTRL_SELECT, PSP_CTRL_START, PSP_CTRL_HOME, PSP_CTRL_HOLD };
|
||||
static int analog_map[256]; /* Map analog inputs to -32768 -> 32767 */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} point;
|
||||
|
||||
/* 4 points define the bezier-curve. */
|
||||
static point a = { 0, 0 };
|
||||
static point b = { 50, 0 };
|
||||
static point c = { 78, 32767 };
|
||||
static point d = { 128, 32767 };
|
||||
|
||||
/* simple linear interpolation between two points */
|
||||
static __inline__ void lerp (point *dest, point *a, point *b, float t)
|
||||
{
|
||||
dest->x = a->x + (b->x - a->x)*t;
|
||||
dest->y = a->y + (b->y - a->y)*t;
|
||||
}
|
||||
|
||||
/* evaluate a point on a bezier-curve. t goes from 0 to 1.0 */
|
||||
static int calc_bezier_y(float t)
|
||||
{
|
||||
point ab, bc, cd, abbc, bccd, dest;
|
||||
lerp (&ab, &a, &b, t); /* point between a and b */
|
||||
lerp (&bc, &b, &c, t); /* point between b and c */
|
||||
lerp (&cd, &c, &d, t); /* point between c and d */
|
||||
lerp (&abbc, &ab, &bc, t); /* point between ab and bc */
|
||||
lerp (&bccd, &bc, &cd, t); /* point between bc and cd */
|
||||
lerp (&dest, &abbc, &bccd, t); /* point on the bezier-curve */
|
||||
return dest.y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect pad data about once per frame
|
||||
*/
|
||||
int JoystickUpdate(void *data)
|
||||
{
|
||||
while (running) {
|
||||
SDL_SemWait(pad_sem);
|
||||
sceCtrlPeekBufferPositive(&pad, 1);
|
||||
SDL_SemPost(pad_sem);
|
||||
/* Delay 1/60th of a second */
|
||||
sceKernelDelayThread(1000000 / 60);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* It should return number of joysticks, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* SDL_numjoysticks = 1; */
|
||||
|
||||
/* Setup input */
|
||||
sceCtrlSetSamplingCycle(0);
|
||||
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
|
||||
|
||||
/* Start thread to read data */
|
||||
if((pad_sem = SDL_CreateSemaphore(1)) == NULL) {
|
||||
return SDL_SetError("Can't create input semaphore");
|
||||
}
|
||||
running = 1;
|
||||
if((thread = SDL_CreateThread(JoystickUpdate, "JoySitckThread",NULL)) == NULL) {
|
||||
return SDL_SetError("Can't create input thread");
|
||||
}
|
||||
|
||||
/* Create an accurate map from analog inputs (0 to 255)
|
||||
to SDL joystick positions (-32768 to 32767) */
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
float t = (float)i/127.0f;
|
||||
analog_map[i+128] = calc_bezier_y(t);
|
||||
analog_map[127-i] = -1 * analog_map[i+128];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return "PSP builtin joypad";
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *SDL_SYS_JoystickName(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
return "PSP controller";
|
||||
|
||||
SDL_SetError("No joystick available with that index");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
{
|
||||
joystick->nbuttons = 14;
|
||||
joystick->naxes = 2;
|
||||
joystick->nhats = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
|
||||
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
|
||||
{
|
||||
int i;
|
||||
enum PspCtrlButtons buttons;
|
||||
enum PspCtrlButtons changed;
|
||||
unsigned char x, y;
|
||||
static enum PspCtrlButtons old_buttons = 0;
|
||||
static unsigned char old_x = 0, old_y = 0;
|
||||
|
||||
SDL_SemWait(pad_sem);
|
||||
buttons = pad.Buttons;
|
||||
x = pad.Lx;
|
||||
y = pad.Ly;
|
||||
SDL_SemPost(pad_sem);
|
||||
|
||||
/* Axes */
|
||||
if(old_x != x) {
|
||||
SDL_PrivateJoystickAxis(joystick, 0, analog_map[x]);
|
||||
old_x = x;
|
||||
}
|
||||
if(old_y != y) {
|
||||
SDL_PrivateJoystickAxis(joystick, 1, analog_map[y]);
|
||||
old_y = y;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
changed = old_buttons ^ buttons;
|
||||
old_buttons = buttons;
|
||||
if(changed) {
|
||||
for(i=0; i<sizeof(button_map)/sizeof(button_map[0]); i++) {
|
||||
if(changed & button_map[i]) {
|
||||
SDL_PrivateJoystickButton(
|
||||
joystick, i,
|
||||
(buttons & button_map[i]) ?
|
||||
SDL_PRESSED : SDL_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sceKernelDelayThread(0);
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
/* Cleanup Threads and Semaphore. */
|
||||
running = 0;
|
||||
SDL_WaitThread(thread, NULL);
|
||||
SDL_DestroySemaphore(pad_sem);
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
/* vim: ts=4 sw=4
|
||||
*/
|
||||
61
src/joystick/sort_controllers.py
Executable file
61
src/joystick/sort_controllers.py
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Script to sort the game controller database entries in SDL_gamecontroller.c
|
||||
|
||||
import re
|
||||
|
||||
|
||||
filename = "SDL_gamecontrollerdb.h"
|
||||
input = open(filename)
|
||||
output = open(filename + ".new", "w")
|
||||
parsing_controllers = False
|
||||
controllers = []
|
||||
controller_guids = {}
|
||||
split_pattern = re.compile(r'([^"]*")([^,]*,)([^,]*,)([^"]*)(".*)')
|
||||
|
||||
def save_controller(line):
|
||||
global controllers
|
||||
match = split_pattern.match(line)
|
||||
entry = [ match.group(1), match.group(2), match.group(3) ]
|
||||
bindings = sorted(match.group(4).split(","))
|
||||
if (bindings[0] == ""):
|
||||
bindings.pop(0)
|
||||
entry.extend(",".join(bindings) + ",")
|
||||
entry.append(match.group(5))
|
||||
controllers.append(entry)
|
||||
|
||||
def write_controllers():
|
||||
global controllers
|
||||
global controller_guids
|
||||
for entry in sorted(controllers, key=lambda entry: entry[2]):
|
||||
line = "".join(entry) + "\n"
|
||||
if (entry[1] in controller_guids):
|
||||
print "Warning: entry '%s' is duplicate of entry '%s'" % (entry[2], controller_guids[entry[1]][2])
|
||||
controller_guids[entry[1]] = entry
|
||||
|
||||
output.write(line)
|
||||
controllers = []
|
||||
controller_guids = {}
|
||||
|
||||
for line in input:
|
||||
if ( parsing_controllers ):
|
||||
if (line.startswith("{")):
|
||||
output.write(line)
|
||||
elif (line.startswith("#endif")):
|
||||
parsing_controllers = False
|
||||
write_controllers()
|
||||
output.write(line)
|
||||
elif (line.startswith("#")):
|
||||
print "Parsing " + line.strip()
|
||||
write_controllers()
|
||||
output.write(line)
|
||||
else:
|
||||
save_controller(line)
|
||||
else:
|
||||
if (line.startswith("static const char *s_ControllerMappings")):
|
||||
parsing_controllers = True
|
||||
|
||||
output.write(line)
|
||||
|
||||
output.close()
|
||||
print "Finished writing %s.new" % filename
|
||||
1755
src/joystick/windows/SDL_dxjoystick.c
Normal file
1755
src/joystick/windows/SDL_dxjoystick.c
Normal file
File diff suppressed because it is too large
Load Diff
144
src/joystick/windows/SDL_dxjoystick_c.h
Normal file
144
src/joystick/windows/SDL_dxjoystick_c.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef SDL_JOYSTICK_DINPUT_H
|
||||
|
||||
/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
|
||||
* A. Formiga's WINMM driver.
|
||||
*
|
||||
* Hats and sliders are completely untested; the app I'm writing this for mostly
|
||||
* doesn't use them and I don't own any joysticks with them.
|
||||
*
|
||||
* We don't bother to use event notification here. It doesn't seem to work
|
||||
* with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
|
||||
* let it return 0 events. */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
|
||||
#include <dinput.h>
|
||||
#define COBJMACROS
|
||||
#include <wbemcli.h>
|
||||
#include <oleauto.h>
|
||||
#include <xinput.h>
|
||||
#include <devguid.h>
|
||||
#include <dbt.h>
|
||||
#include <xinput.h>
|
||||
|
||||
/* typedef's for XInput structs we use */
|
||||
typedef struct
|
||||
{
|
||||
WORD wButtons;
|
||||
BYTE bLeftTrigger;
|
||||
BYTE bRightTrigger;
|
||||
SHORT sThumbLX;
|
||||
SHORT sThumbLY;
|
||||
SHORT sThumbRX;
|
||||
SHORT sThumbRY;
|
||||
DWORD dwPaddingReserved;
|
||||
} XINPUT_GAMEPAD_EX;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwPacketNumber;
|
||||
XINPUT_GAMEPAD_EX Gamepad;
|
||||
} XINPUT_STATE_EX;
|
||||
|
||||
/* Forward decl's for XInput API's we load dynamically and use if available */
|
||||
typedef DWORD (WINAPI *XInputGetState_t)
|
||||
(
|
||||
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
|
||||
XINPUT_STATE_EX* pState /* [out] Receives the current state */
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *XInputSetState_t)
|
||||
(
|
||||
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
|
||||
XINPUT_VIBRATION* pVibration /* [in, out] The vibration information to send to the controller */
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *XInputGetCapabilities_t)
|
||||
(
|
||||
DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */
|
||||
DWORD dwFlags, /* [in] Input flags that identify the device type */
|
||||
XINPUT_CAPABILITIES* pCapabilities /* [out] Receives the capabilities */
|
||||
);
|
||||
|
||||
extern int WIN_LoadXInputDLL(void);
|
||||
extern void WIN_UnloadXInputDLL(void);
|
||||
|
||||
extern XInputGetState_t SDL_XInputGetState;
|
||||
extern XInputSetState_t SDL_XInputSetState;
|
||||
extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
|
||||
extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
|
||||
|
||||
#define XINPUTGETSTATE SDL_XInputGetState
|
||||
#define XINPUTSETSTATE SDL_XInputSetState
|
||||
#define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities
|
||||
#define INVALID_XINPUT_USERID 255
|
||||
#define SDL_XINPUT_MAX_DEVICES 4
|
||||
|
||||
#ifndef XINPUT_CAPS_FFB_SUPPORTED
|
||||
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */
|
||||
|
||||
|
||||
/* local types */
|
||||
typedef enum Type
|
||||
{ BUTTON, AXIS, HAT } Type;
|
||||
|
||||
typedef struct input_t
|
||||
{
|
||||
/* DirectInput offset for this input type: */
|
||||
DWORD ofs;
|
||||
|
||||
/* Button, axis or hat: */
|
||||
Type type;
|
||||
|
||||
/* SDL input offset: */
|
||||
Uint8 num;
|
||||
} input_t;
|
||||
|
||||
/* The private structure used to keep track of a joystick */
|
||||
struct joystick_hwdata
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 InputDevice;
|
||||
DIDEVCAPS Capabilities;
|
||||
int buffered;
|
||||
SDL_JoystickGUID guid;
|
||||
|
||||
input_t Inputs[MAX_INPUTS];
|
||||
int NumInputs;
|
||||
int NumSliders;
|
||||
Uint8 removed;
|
||||
Uint8 send_remove_event;
|
||||
Uint8 bXInputDevice; /* 1 if this device supports using the xinput API rather than DirectInput */
|
||||
Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
|
||||
Uint8 userid; /* XInput userid index for this joystick */
|
||||
Uint8 currentXInputSlot; /* the current position to write to in XInputState below, used so we can compare old and new values */
|
||||
XINPUT_STATE_EX XInputState[2];
|
||||
};
|
||||
|
||||
#endif /* SDL_JOYSTICK_DINPUT_H */
|
||||
474
src/joystick/windows/SDL_mmjoystick.c
Normal file
474
src/joystick/windows/SDL_mmjoystick.c
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_WINMM
|
||||
|
||||
/* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include <mmsystem.h>
|
||||
#include <regstr.h>
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
#define MAX_JOYSTICKS 16
|
||||
#define MAX_AXES 6 /* each joystick can have up to 6 axes */
|
||||
#define MAX_BUTTONS 32 /* and 32 buttons */
|
||||
#define AXIS_MIN -32768 /* minimum value for axis coordinate */
|
||||
#define AXIS_MAX 32767 /* maximum value for axis coordinate */
|
||||
/* limit axis to 256 possible positions to filter out noise */
|
||||
#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256)
|
||||
#define JOY_BUTTON_FLAG(n) (1<<n)
|
||||
|
||||
|
||||
/* array to hold joystick ID values */
|
||||
static UINT SYS_JoystickID[MAX_JOYSTICKS];
|
||||
static JOYCAPS SYS_Joystick[MAX_JOYSTICKS];
|
||||
static char *SYS_JoystickName[MAX_JOYSTICKS];
|
||||
|
||||
/* The private structure used to keep track of a joystick */
|
||||
struct joystick_hwdata
|
||||
{
|
||||
/* joystick ID */
|
||||
UINT id;
|
||||
|
||||
/* values used to translate device-specific coordinates into
|
||||
SDL-standard ranges */
|
||||
struct _transaxis
|
||||
{
|
||||
int offset;
|
||||
float scale;
|
||||
} transaxis[6];
|
||||
};
|
||||
|
||||
/* Convert a Windows Multimedia API return code to a text message */
|
||||
static void SetMMerror(char *function, int code);
|
||||
|
||||
|
||||
static char *
|
||||
GetJoystickName(int index, const char *szRegKey)
|
||||
{
|
||||
/* added 7/24/2004 by Eckhard Stolberg */
|
||||
/*
|
||||
see if there is a joystick for the current
|
||||
index (1-16) listed in the registry
|
||||
*/
|
||||
char *name = NULL;
|
||||
HKEY hTopKey;
|
||||
HKEY hKey;
|
||||
DWORD regsize;
|
||||
LONG regresult;
|
||||
char regkey[256];
|
||||
char regvalue[256];
|
||||
char regname[256];
|
||||
|
||||
SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s\\%s",
|
||||
REGSTR_PATH_JOYCONFIG, szRegKey, REGSTR_KEY_JOYCURR);
|
||||
hTopKey = HKEY_LOCAL_MACHINE;
|
||||
regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
|
||||
if (regresult != ERROR_SUCCESS) {
|
||||
hTopKey = HKEY_CURRENT_USER;
|
||||
regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
|
||||
}
|
||||
if (regresult != ERROR_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find the registry key name for the joystick's properties */
|
||||
regsize = sizeof(regname);
|
||||
SDL_snprintf(regvalue, SDL_arraysize(regvalue), "Joystick%d%s", index + 1,
|
||||
REGSTR_VAL_JOYOEMNAME);
|
||||
regresult =
|
||||
RegQueryValueExA(hKey, regvalue, 0, 0, (LPBYTE) regname, ®size);
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if (regresult != ERROR_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* open that registry key */
|
||||
SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s", REGSTR_PATH_JOYOEM,
|
||||
regname);
|
||||
regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
|
||||
if (regresult != ERROR_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find the size for the OEM name text */
|
||||
regsize = sizeof(regvalue);
|
||||
regresult =
|
||||
RegQueryValueExA(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, NULL, ®size);
|
||||
if (regresult == ERROR_SUCCESS) {
|
||||
/* allocate enough memory for the OEM name text ... */
|
||||
name = (char *) SDL_malloc(regsize);
|
||||
if (name) {
|
||||
/* ... and read it from the registry */
|
||||
regresult = RegQueryValueExA(hKey,
|
||||
REGSTR_VAL_JOYOEMNAME, 0, 0,
|
||||
(LPBYTE) name, ®size);
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return (name);
|
||||
}
|
||||
|
||||
static int SDL_SYS_numjoysticks = 0;
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
int i;
|
||||
int maxdevs;
|
||||
JOYINFOEX joyinfo;
|
||||
JOYCAPS joycaps;
|
||||
MMRESULT result;
|
||||
|
||||
/* Reset the joystick ID & name mapping tables */
|
||||
for (i = 0; i < MAX_JOYSTICKS; ++i) {
|
||||
SYS_JoystickID[i] = 0;
|
||||
SYS_JoystickName[i] = NULL;
|
||||
}
|
||||
|
||||
/* Loop over all potential joystick devices */
|
||||
SDL_SYS_numjoysticks = 0;
|
||||
maxdevs = joyGetNumDevs();
|
||||
for (i = JOYSTICKID1; i < maxdevs && SDL_SYS_numjoysticks < MAX_JOYSTICKS; ++i) {
|
||||
|
||||
joyinfo.dwSize = sizeof(joyinfo);
|
||||
joyinfo.dwFlags = JOY_RETURNALL;
|
||||
result = joyGetPosEx(i, &joyinfo);
|
||||
if (result == JOYERR_NOERROR) {
|
||||
result = joyGetDevCaps(i, &joycaps, sizeof(joycaps));
|
||||
if (result == JOYERR_NOERROR) {
|
||||
SYS_JoystickID[SDL_SYS_numjoysticks] = i;
|
||||
SYS_Joystick[SDL_SYS_numjoysticks] = joycaps;
|
||||
SYS_JoystickName[SDL_SYS_numjoysticks] =
|
||||
GetJoystickName(i, joycaps.szRegKey);
|
||||
SDL_SYS_numjoysticks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (SDL_SYS_numjoysticks);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return SDL_SYS_numjoysticks;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
if (SYS_JoystickName[device_index] != NULL) {
|
||||
return (SYS_JoystickName[device_index]);
|
||||
} else {
|
||||
return (SYS_Joystick[device_index].szPname);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
int index, i;
|
||||
int caps_flags[MAX_AXES - 2] =
|
||||
{ JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV };
|
||||
int axis_min[MAX_AXES], axis_max[MAX_AXES];
|
||||
|
||||
|
||||
/* shortcut */
|
||||
index = device_index;
|
||||
axis_min[0] = SYS_Joystick[index].wXmin;
|
||||
axis_max[0] = SYS_Joystick[index].wXmax;
|
||||
axis_min[1] = SYS_Joystick[index].wYmin;
|
||||
axis_max[1] = SYS_Joystick[index].wYmax;
|
||||
axis_min[2] = SYS_Joystick[index].wZmin;
|
||||
axis_max[2] = SYS_Joystick[index].wZmax;
|
||||
axis_min[3] = SYS_Joystick[index].wRmin;
|
||||
axis_max[3] = SYS_Joystick[index].wRmax;
|
||||
axis_min[4] = SYS_Joystick[index].wUmin;
|
||||
axis_max[4] = SYS_Joystick[index].wUmax;
|
||||
axis_min[5] = SYS_Joystick[index].wVmin;
|
||||
axis_max[5] = SYS_Joystick[index].wVmax;
|
||||
|
||||
/* allocate memory for system specific hardware data */
|
||||
joystick->instance_id = device_index;
|
||||
joystick->hwdata =
|
||||
(struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata));
|
||||
if (joystick->hwdata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
|
||||
|
||||
/* set hardware data */
|
||||
joystick->hwdata->id = SYS_JoystickID[index];
|
||||
for (i = 0; i < MAX_AXES; ++i) {
|
||||
if ((i < 2) || (SYS_Joystick[index].wCaps & caps_flags[i - 2])) {
|
||||
joystick->hwdata->transaxis[i].offset = AXIS_MIN - axis_min[i];
|
||||
joystick->hwdata->transaxis[i].scale =
|
||||
(float) (AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]);
|
||||
} else {
|
||||
joystick->hwdata->transaxis[i].offset = 0;
|
||||
joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */
|
||||
}
|
||||
}
|
||||
|
||||
/* fill nbuttons, naxes, and nhats fields */
|
||||
joystick->nbuttons = SYS_Joystick[index].wNumButtons;
|
||||
joystick->naxes = SYS_Joystick[index].wNumAxes;
|
||||
if (SYS_Joystick[index].wCaps & JOYCAPS_HASPOV) {
|
||||
joystick->nhats = 1;
|
||||
} else {
|
||||
joystick->nhats = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static Uint8
|
||||
TranslatePOV(DWORD value)
|
||||
{
|
||||
Uint8 pos;
|
||||
|
||||
pos = SDL_HAT_CENTERED;
|
||||
if (value != JOY_POVCENTERED) {
|
||||
if ((value > JOY_POVLEFT) || (value < JOY_POVRIGHT)) {
|
||||
pos |= SDL_HAT_UP;
|
||||
}
|
||||
if ((value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD)) {
|
||||
pos |= SDL_HAT_RIGHT;
|
||||
}
|
||||
if ((value > JOY_POVRIGHT) && (value < JOY_POVLEFT)) {
|
||||
pos |= SDL_HAT_DOWN;
|
||||
}
|
||||
if (value > JOY_POVBACKWARD) {
|
||||
pos |= SDL_HAT_LEFT;
|
||||
}
|
||||
}
|
||||
return (pos);
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
MMRESULT result;
|
||||
int i;
|
||||
DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ,
|
||||
JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
|
||||
};
|
||||
DWORD pos[MAX_AXES];
|
||||
struct _transaxis *transaxis;
|
||||
int value, change;
|
||||
JOYINFOEX joyinfo;
|
||||
|
||||
joyinfo.dwSize = sizeof(joyinfo);
|
||||
joyinfo.dwFlags = JOY_RETURNALL | JOY_RETURNPOVCTS;
|
||||
if (!joystick->hats) {
|
||||
joyinfo.dwFlags &= ~(JOY_RETURNPOV | JOY_RETURNPOVCTS);
|
||||
}
|
||||
result = joyGetPosEx(joystick->hwdata->id, &joyinfo);
|
||||
if (result != JOYERR_NOERROR) {
|
||||
SetMMerror("joyGetPosEx", result);
|
||||
return;
|
||||
}
|
||||
|
||||
/* joystick motion events */
|
||||
pos[0] = joyinfo.dwXpos;
|
||||
pos[1] = joyinfo.dwYpos;
|
||||
pos[2] = joyinfo.dwZpos;
|
||||
pos[3] = joyinfo.dwRpos;
|
||||
pos[4] = joyinfo.dwUpos;
|
||||
pos[5] = joyinfo.dwVpos;
|
||||
|
||||
transaxis = joystick->hwdata->transaxis;
|
||||
for (i = 0; i < joystick->naxes; i++) {
|
||||
if (joyinfo.dwFlags & flags[i]) {
|
||||
value =
|
||||
(int) (((float) pos[i] +
|
||||
transaxis[i].offset) * transaxis[i].scale);
|
||||
change = (value - joystick->axes[i]);
|
||||
if ((change < -JOY_AXIS_THRESHOLD)
|
||||
|| (change > JOY_AXIS_THRESHOLD)) {
|
||||
SDL_PrivateJoystickAxis(joystick, (Uint8) i, (Sint16) value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* joystick button events */
|
||||
if (joyinfo.dwFlags & JOY_RETURNBUTTONS) {
|
||||
for (i = 0; i < joystick->nbuttons; ++i) {
|
||||
if (joyinfo.dwButtons & JOY_BUTTON_FLAG(i)) {
|
||||
if (!joystick->buttons[i]) {
|
||||
SDL_PrivateJoystickButton(joystick, (Uint8) i,
|
||||
SDL_PRESSED);
|
||||
}
|
||||
} else {
|
||||
if (joystick->buttons[i]) {
|
||||
SDL_PrivateJoystickButton(joystick, (Uint8) i,
|
||||
SDL_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* joystick hat events */
|
||||
if (joyinfo.dwFlags & JOY_RETURNPOV) {
|
||||
Uint8 pos;
|
||||
|
||||
pos = TranslatePOV(joyinfo.dwPOV);
|
||||
if (pos != joystick->hats[0]) {
|
||||
SDL_PrivateJoystickHat(joystick, 0, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata != NULL) {
|
||||
/* free system specific hardware data */
|
||||
SDL_free(joystick->hwdata);
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_JOYSTICKS; i++) {
|
||||
if (SYS_JoystickName[i] != NULL) {
|
||||
SDL_free(SYS_JoystickName[i]);
|
||||
SYS_JoystickName[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
/* implementation functions */
|
||||
void
|
||||
SetMMerror(char *function, int code)
|
||||
{
|
||||
static char *error;
|
||||
static char errbuf[1024];
|
||||
|
||||
errbuf[0] = 0;
|
||||
switch (code) {
|
||||
case MMSYSERR_NODRIVER:
|
||||
error = "Joystick driver not present";
|
||||
break;
|
||||
|
||||
case MMSYSERR_INVALPARAM:
|
||||
case JOYERR_PARMS:
|
||||
error = "Invalid parameter(s)";
|
||||
break;
|
||||
|
||||
case MMSYSERR_BADDEVICEID:
|
||||
error = "Bad device ID";
|
||||
break;
|
||||
|
||||
case JOYERR_UNPLUGGED:
|
||||
error = "Joystick not attached";
|
||||
break;
|
||||
|
||||
case JOYERR_NOCANDO:
|
||||
error = "Can't capture joystick input";
|
||||
break;
|
||||
|
||||
default:
|
||||
SDL_snprintf(errbuf, SDL_arraysize(errbuf),
|
||||
"%s: Unknown Multimedia system error: 0x%x",
|
||||
function, code);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!errbuf[0]) {
|
||||
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
|
||||
error);
|
||||
}
|
||||
SDL_SetError("%s", errbuf);
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_WINMM */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user