mirror of
https://github.com/encounter/SDL.git
synced 2025-12-13 23:26:18 +00:00
Added a README file regarding WinRT support
To note, this file is currently formatted with CRLF line endings, rather than LF, to allow the file to be viewed with Notepad.
This commit is contained in:
1333
src/joystick/SDL_gamecontroller.c
Normal file
1333
src/joystick/SDL_gamecontroller.c
Normal file
File diff suppressed because it is too large
Load Diff
76
src/joystick/SDL_gamecontrollerdb.h
Normal file
76
src/joystick/SDL_gamecontrollerdb.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
|
||||
/* 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.
|
||||
|
||||
Alternatively, you can use the app located in test/controllermap
|
||||
*/
|
||||
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. */
|
||||
"4d6963726f736f66742050432d6a6f79,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a5,righty:a4,x:b1,y:b2,",
|
||||
"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,",
|
||||
"4c05c405000000000000504944564944,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,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(SDL_JOYSTICK_XINPUT)
|
||||
"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,",
|
||||
"4c05000000000000c405000000000000,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"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,",
|
||||
"050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
|
||||
"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,",
|
||||
"030000004c050000c405000011010000,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"03000000de280000ff11000001000000,Valve Streaming Gamepad,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,",
|
||||
"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,",
|
||||
"030000005e0400009102000007010000,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: */
|
||||
854
src/joystick/SDL_joystick.c
Normal file
854
src/joystick/SDL_joystick.c
Normal file
@@ -0,0 +1,854 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
SDL_free(joystick->name);
|
||||
|
||||
/* Free the data associated with this joystick */
|
||||
SDL_free(joystick->axes);
|
||||
SDL_free(joystick->hats);
|
||||
SDL_free(joystick->balls);
|
||||
SDL_free(joystick->buttons);
|
||||
SDL_free(joystick);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
SDL_JoystickGUID emptyGUID;
|
||||
SDL_zero( emptyGUID );
|
||||
return emptyGUID;
|
||||
}
|
||||
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)/2; i++ )
|
||||
{
|
||||
/* each input byte writes 2 ascii chars, and might write a null byte. */
|
||||
/* If we don't have room for next input byte, stop */
|
||||
unsigned char c = guid.data[i];
|
||||
|
||||
*pszGUID++ = k_rgchHexToASCII[ c >> 4 ];
|
||||
*pszGUID++ = k_rgchHexToASCII[ c & 0x0F ];
|
||||
}
|
||||
*pszGUID = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Purpose: Returns the 4 bit nibble for a hex character
|
||||
* Input : c -
|
||||
* Output : unsigned char
|
||||
*-----------------------------------------------------------------------------*/
|
||||
static unsigned char nibble( char c )
|
||||
{
|
||||
if ( ( c >= '0' ) &&
|
||||
( c <= '9' ) )
|
||||
{
|
||||
return (unsigned char)(c - '0');
|
||||
}
|
||||
|
||||
if ( ( c >= 'A' ) &&
|
||||
( c <= 'F' ) )
|
||||
{
|
||||
return (unsigned char)(c - 'A' + 0x0a);
|
||||
}
|
||||
|
||||
if ( ( c >= 'a' ) &&
|
||||
( c <= 'f' ) )
|
||||
{
|
||||
return (unsigned char)(c - 'a' + 0x0a);
|
||||
}
|
||||
|
||||
/* received an invalid character, and no real way to return an error */
|
||||
/* AssertMsg1( false, "Q_nibble invalid hex character '%c' ", c ); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* convert the string version of a joystick guid to the struct */
|
||||
SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
int maxoutputbytes= sizeof(guid);
|
||||
size_t len = SDL_strlen( pchGUID );
|
||||
Uint8 *p;
|
||||
size_t i;
|
||||
|
||||
/* Make sure it's even */
|
||||
len = ( len ) & ~0x1;
|
||||
|
||||
SDL_memset( &guid, 0x00, sizeof(guid) );
|
||||
|
||||
p = (Uint8 *)&guid;
|
||||
for ( i = 0;
|
||||
( i < len ) && ( ( p - (Uint8 *)&guid ) < maxoutputbytes );
|
||||
i+=2, p++ )
|
||||
{
|
||||
*p = ( nibble( pchGUID[i] ) << 4 ) | nibble( pchGUID[i+1] );
|
||||
}
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
/* 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-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
/* 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: */
|
||||
117
src/joystick/SDL_sysjoystick.h
Normal file
117
src/joystick/SDL_sysjoystick.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
/* 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);
|
||||
|
||||
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
|
||||
/* Function to get the current instance id of the joystick located at device_index */
|
||||
extern SDL_bool SDL_SYS_IsXInputDeviceIndex( int device_index );
|
||||
extern SDL_bool SDL_SYS_IsXInputJoystick(SDL_Joystick * joystick);
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
582
src/joystick/android/SDL_sysjoystick.c
Normal file
582
src/joystick/android/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
|
||||
#include <stdio.h> /* For the definition of NULL */
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_events.h"
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_sysjoystick_c.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
#include "android/keycodes.h"
|
||||
|
||||
/* As of platform android-14, android/keycodes.h is missing these defines */
|
||||
#ifndef AKEYCODE_BUTTON_1
|
||||
#define AKEYCODE_BUTTON_1 188
|
||||
#define AKEYCODE_BUTTON_2 189
|
||||
#define AKEYCODE_BUTTON_3 190
|
||||
#define AKEYCODE_BUTTON_4 191
|
||||
#define AKEYCODE_BUTTON_5 192
|
||||
#define AKEYCODE_BUTTON_6 193
|
||||
#define AKEYCODE_BUTTON_7 194
|
||||
#define AKEYCODE_BUTTON_8 195
|
||||
#define AKEYCODE_BUTTON_9 196
|
||||
#define AKEYCODE_BUTTON_10 197
|
||||
#define AKEYCODE_BUTTON_11 198
|
||||
#define AKEYCODE_BUTTON_12 199
|
||||
#define AKEYCODE_BUTTON_13 200
|
||||
#define AKEYCODE_BUTTON_14 201
|
||||
#define AKEYCODE_BUTTON_15 202
|
||||
#define AKEYCODE_BUTTON_16 203
|
||||
#endif
|
||||
|
||||
#define ANDROID_ACCELEROMETER_NAME "Android Accelerometer"
|
||||
#define ANDROID_ACCELEROMETER_DEVICE_ID INT_MIN
|
||||
#define ANDROID_MAX_NBUTTONS 36
|
||||
|
||||
static SDL_joylist_item * JoystickByDeviceId(int device_id);
|
||||
|
||||
static SDL_joylist_item *SDL_joylist = NULL;
|
||||
static SDL_joylist_item *SDL_joylist_tail = NULL;
|
||||
static int numjoysticks = 0;
|
||||
static int instance_counter = 0;
|
||||
|
||||
|
||||
/* Function to convert Android keyCodes into SDL ones.
|
||||
* This code manipulation is done to get a sequential list of codes.
|
||||
* FIXME: This is only suited for the case where we use a fixed number of buttons determined by ANDROID_MAX_NBUTTONS
|
||||
*/
|
||||
static int
|
||||
keycode_to_SDL(int keycode)
|
||||
{
|
||||
/* FIXME: If this function gets too unwiedly in the future, replace with a lookup table */
|
||||
int button = 0;
|
||||
switch(keycode)
|
||||
{
|
||||
/* Some gamepad buttons (API 9) */
|
||||
case AKEYCODE_BUTTON_A:
|
||||
button = SDL_CONTROLLER_BUTTON_A;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_B:
|
||||
button = SDL_CONTROLLER_BUTTON_B;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_X:
|
||||
button = SDL_CONTROLLER_BUTTON_X;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_Y:
|
||||
button = SDL_CONTROLLER_BUTTON_Y;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_L1:
|
||||
button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_R1:
|
||||
button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_THUMBL:
|
||||
button = SDL_CONTROLLER_BUTTON_LEFTSTICK;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_THUMBR:
|
||||
button = SDL_CONTROLLER_BUTTON_RIGHTSTICK;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_START:
|
||||
button = SDL_CONTROLLER_BUTTON_START;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_SELECT:
|
||||
button = SDL_CONTROLLER_BUTTON_BACK;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_MODE:
|
||||
button = SDL_CONTROLLER_BUTTON_GUIDE;
|
||||
break;
|
||||
case AKEYCODE_BUTTON_L2:
|
||||
button = SDL_CONTROLLER_BUTTON_MAX; /* Not supported by GameController */
|
||||
break;
|
||||
case AKEYCODE_BUTTON_R2:
|
||||
button = SDL_CONTROLLER_BUTTON_MAX+1; /* Not supported by GameController */
|
||||
break;
|
||||
case AKEYCODE_BUTTON_C:
|
||||
button = SDL_CONTROLLER_BUTTON_MAX+2; /* Not supported by GameController */
|
||||
break;
|
||||
case AKEYCODE_BUTTON_Z:
|
||||
button = SDL_CONTROLLER_BUTTON_MAX+3; /* Not supported by GameController */
|
||||
break;
|
||||
|
||||
/* D-Pad key codes (API 1) */
|
||||
case AKEYCODE_DPAD_UP:
|
||||
button = SDL_CONTROLLER_BUTTON_DPAD_UP;
|
||||
break;
|
||||
case AKEYCODE_DPAD_DOWN:
|
||||
button = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
|
||||
break;
|
||||
case AKEYCODE_DPAD_LEFT:
|
||||
button = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
|
||||
break;
|
||||
case AKEYCODE_DPAD_RIGHT:
|
||||
button = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
|
||||
break;
|
||||
case AKEYCODE_DPAD_CENTER:
|
||||
button = SDL_CONTROLLER_BUTTON_MAX+4; /* Not supported by GameController */
|
||||
break;
|
||||
|
||||
/* More gamepad buttons (API 12), these get mapped to 20...35*/
|
||||
case AKEYCODE_BUTTON_1:
|
||||
case AKEYCODE_BUTTON_2:
|
||||
case AKEYCODE_BUTTON_3:
|
||||
case AKEYCODE_BUTTON_4:
|
||||
case AKEYCODE_BUTTON_5:
|
||||
case AKEYCODE_BUTTON_6:
|
||||
case AKEYCODE_BUTTON_7:
|
||||
case AKEYCODE_BUTTON_8:
|
||||
case AKEYCODE_BUTTON_9:
|
||||
case AKEYCODE_BUTTON_10:
|
||||
case AKEYCODE_BUTTON_11:
|
||||
case AKEYCODE_BUTTON_12:
|
||||
case AKEYCODE_BUTTON_13:
|
||||
case AKEYCODE_BUTTON_14:
|
||||
case AKEYCODE_BUTTON_15:
|
||||
case AKEYCODE_BUTTON_16:
|
||||
button = keycode - AKEYCODE_BUTTON_1 + SDL_CONTROLLER_BUTTON_MAX + 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is here in case future generations, probably with six fingers per hand,
|
||||
* happily add new cases up above and forget to update the max number of buttons.
|
||||
*/
|
||||
SDL_assert(button < ANDROID_MAX_NBUTTONS);
|
||||
return button;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
Android_OnPadDown(int device_id, int keycode)
|
||||
{
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
if (button >= 0) {
|
||||
item = JoystickByDeviceId(device_id);
|
||||
if (item && item->joystick) {
|
||||
SDL_PrivateJoystickButton(item->joystick, button , SDL_PRESSED);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
Android_OnPadUp(int device_id, int keycode)
|
||||
{
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
if (button >= 0) {
|
||||
item = JoystickByDeviceId(device_id);
|
||||
if (item && item->joystick) {
|
||||
SDL_PrivateJoystickButton(item->joystick, button, SDL_RELEASED);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
Android_OnJoy(int device_id, int axis, float value)
|
||||
{
|
||||
/* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
|
||||
SDL_joylist_item *item = JoystickByDeviceId(device_id);
|
||||
if (item && item->joystick) {
|
||||
SDL_PrivateJoystickAxis(item->joystick, axis, (Sint16) (32767.*value) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Android_OnHat(int device_id, int hat_id, int x, int y)
|
||||
{
|
||||
const Uint8 position_map[3][3] = {
|
||||
{SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
|
||||
{SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
|
||||
{SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
|
||||
};
|
||||
|
||||
if (x >= -1 && x <=1 && y >= -1 && y <= 1) {
|
||||
SDL_joylist_item *item = JoystickByDeviceId(device_id);
|
||||
if (item && item->joystick) {
|
||||
SDL_PrivateJoystickHat(item->joystick, hat_id, position_map[y+1][x+1] );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Android_AddJoystick(int device_id, const char *name, SDL_bool is_accelerometer, int nbuttons, int naxes, int nhats, int nballs)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
SDL_joylist_item *item;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
if(JoystickByDeviceId(device_id) != NULL || name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
|
||||
item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_zerop(item);
|
||||
item->guid = guid;
|
||||
item->device_id = device_id;
|
||||
item->name = SDL_strdup(name);
|
||||
if ( item->name == NULL ) {
|
||||
SDL_free(item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
item->is_accelerometer = is_accelerometer;
|
||||
if (nbuttons > -1) {
|
||||
item->nbuttons = nbuttons;
|
||||
}
|
||||
else {
|
||||
item->nbuttons = ANDROID_MAX_NBUTTONS;
|
||||
}
|
||||
item->naxes = naxes;
|
||||
item->nhats = nhats;
|
||||
item->nballs = nballs;
|
||||
item->device_instance = instance_counter++;
|
||||
if (SDL_joylist_tail == NULL) {
|
||||
SDL_joylist = SDL_joylist_tail = item;
|
||||
} else {
|
||||
SDL_joylist_tail->next = item;
|
||||
SDL_joylist_tail = item;
|
||||
}
|
||||
|
||||
/* Need to increment the joystick count before we post the event */
|
||||
++numjoysticks;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = (numjoysticks - 1);
|
||||
if ( (SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
SDL_Log("Added joystick %s with device_id %d", name, device_id);
|
||||
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
int
|
||||
Android_RemoveJoystick(int device_id)
|
||||
{
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
SDL_joylist_item *prev = NULL;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
/* Don't call JoystickByDeviceId here or there'll be an infinite loop! */
|
||||
while (item != NULL) {
|
||||
if (item->device_id == device_id) {
|
||||
break;
|
||||
}
|
||||
prev = item;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int retval = item->device_instance;
|
||||
if (item->joystick) {
|
||||
item->joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
if (prev != NULL) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
SDL_assert(SDL_joylist == item);
|
||||
SDL_joylist = item->next;
|
||||
}
|
||||
if (item == SDL_joylist_tail) {
|
||||
SDL_joylist_tail = prev;
|
||||
}
|
||||
|
||||
/* Need to decrement the joystick count before we post the event */
|
||||
--numjoysticks;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = item->device_instance;
|
||||
if ( (SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
SDL_Log("Removed joystick with device_id %d", device_id);
|
||||
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
const char *hint;
|
||||
SDL_SYS_JoystickDetect();
|
||||
|
||||
hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
|
||||
if (!hint || SDL_atoi(hint)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, SDL_TRUE, 0, 3, 0, 0);
|
||||
}
|
||||
|
||||
return (numjoysticks);
|
||||
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
/* Support for device connect/disconnect is API >= 16 only,
|
||||
* so we poll every three seconds
|
||||
* Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html
|
||||
*/
|
||||
static Uint32 timeout = 0;
|
||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
|
||||
timeout = SDL_GetTicks() + 3000;
|
||||
Android_JNI_PollInputDevices();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_joylist_item *
|
||||
JoystickByDevIndex(int device_index)
|
||||
{
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
|
||||
if ((device_index < 0) || (device_index >= numjoysticks)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (device_index > 0) {
|
||||
SDL_assert(item != NULL);
|
||||
device_index--;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static SDL_joylist_item *
|
||||
JoystickByDeviceId(int device_id)
|
||||
{
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
|
||||
while (item != NULL) {
|
||||
if (item->device_id == device_id) {
|
||||
return item;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
/* Joystick not found, try adding it */
|
||||
SDL_SYS_JoystickDetect();
|
||||
|
||||
while (item != NULL) {
|
||||
if (item->device_id == device_id) {
|
||||
return item;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return JoystickByDevIndex(device_index)->name;
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return JoystickByDevIndex(device_index)->device_instance;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
SDL_joylist_item *item = JoystickByDevIndex(device_index);
|
||||
|
||||
if (item == NULL ) {
|
||||
return SDL_SetError("No such device");
|
||||
}
|
||||
|
||||
if (item->joystick != NULL) {
|
||||
return SDL_SetError("Joystick already opened");
|
||||
}
|
||||
|
||||
joystick->instance_id = item->device_instance;
|
||||
joystick->hwdata = (struct joystick_hwdata *) item;
|
||||
item->joystick = joystick;
|
||||
joystick->nhats = item->nhats;
|
||||
joystick->nballs = item->nballs;
|
||||
joystick->nbuttons = item->nbuttons;
|
||||
joystick->naxes = item->naxes;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return !joystick->closed && (joystick->hwdata != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
int i;
|
||||
Sint16 value;
|
||||
float values[3];
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
|
||||
while (item) {
|
||||
if (item->is_accelerometer) {
|
||||
if (item->joystick) {
|
||||
if (Android_JNI_GetAccelerometerValues(values)) {
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
value = (Sint16)(values[i] * 32767.0f);
|
||||
SDL_PrivateJoystickAxis(item->joystick, i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata) {
|
||||
((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
joystick->closed = 1;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
SDL_joylist_item *item = NULL;
|
||||
SDL_joylist_item *next = NULL;
|
||||
|
||||
for (item = SDL_joylist; item; item = next) {
|
||||
next = item->next;
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
}
|
||||
|
||||
SDL_joylist = SDL_joylist_tail = NULL;
|
||||
|
||||
numjoysticks = 0;
|
||||
instance_counter = 0;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
return JoystickByDevIndex(device_index)->guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
|
||||
if (joystick->hwdata != NULL) {
|
||||
return ((SDL_joylist_item*)joystick->hwdata)->guid;
|
||||
}
|
||||
|
||||
SDL_zero(guid);
|
||||
return guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_ANDROID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
52
src/joystick/android/SDL_sysjoystick_c.h
Normal file
52
src/joystick/android/SDL_sysjoystick_c.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 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
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
extern int Android_OnPadDown(int device_id, int keycode);
|
||||
extern int Android_OnPadUp(int device_id, int keycode);
|
||||
extern int Android_OnJoy(int device_id, int axisnum, float value);
|
||||
extern int Android_OnHat(int device_id, int hat_id, int x, int y);
|
||||
extern int Android_AddJoystick(int device_id, const char *name, SDL_bool is_accelerometer, int nbuttons, int naxes, int nhats, int nballs);
|
||||
extern int Android_RemoveJoystick(int device_id);
|
||||
|
||||
/* A linked list of available joysticks */
|
||||
typedef struct SDL_joylist_item
|
||||
{
|
||||
int device_instance;
|
||||
int device_id; /* Android's device id */
|
||||
char *name; /* "SideWinder 3D Pro" or whatever */
|
||||
SDL_JoystickGUID guid;
|
||||
SDL_bool is_accelerometer;
|
||||
SDL_Joystick *joystick;
|
||||
int nbuttons, naxes, nhats, nballs;
|
||||
|
||||
struct SDL_joylist_item *next;
|
||||
} SDL_joylist_item;
|
||||
|
||||
typedef SDL_joylist_item joystick_hwdata;
|
||||
|
||||
#endif /* SDL_JOYSTICK_ANDROID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
660
src/joystick/bsd/SDL_sysjoystick.c
Normal file
660
src/joystick/bsd/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,660 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_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) {
|
||||
while (read(joy->hwdata->fd, &gameport, sizeof gameport) == sizeof gameport) {
|
||||
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;
|
||||
|
||||
while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
|
||||
#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);*/
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
SDL_free(joynames[i]);
|
||||
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)
|
||||
{
|
||||
SDL_free(r->buf);
|
||||
r->status = SREPORT_UNINIT;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_USBHID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
824
src/joystick/darwin/SDL_sysjoystick.c
Normal file
824
src/joystick/darwin/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,824 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_IOKIT
|
||||
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
/* For force feedback testing. */
|
||||
#include <ForceFeedback/ForceFeedback.h>
|
||||
#include <ForceFeedback/ForceFeedbackConstants.h>
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "SDL_sysjoystick_c.h"
|
||||
#include "SDL_events.h"
|
||||
#include "../../haptic/darwin/SDL_syshaptic_c.h" /* For haptic hot plugging */
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
/* The base object of the HID Manager API */
|
||||
static IOHIDManagerRef hidman = NULL;
|
||||
|
||||
/* Linked list of all available devices */
|
||||
static recDevice *gpDeviceList = NULL;
|
||||
|
||||
/* if SDL_TRUE then a device was added since the last update call */
|
||||
static SDL_bool s_bDeviceAdded = SDL_FALSE;
|
||||
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
|
||||
|
||||
/* static incrementing counter for new joystick devices seen on the system. Devices should start with index 0 */
|
||||
static int s_joystick_instance_id = -1;
|
||||
|
||||
|
||||
static void
|
||||
FreeElementList(recElement *pElement)
|
||||
{
|
||||
while (pElement) {
|
||||
recElement *pElementNext = pElement->pNext;
|
||||
SDL_free(pElement);
|
||||
pElement = pElementNext;
|
||||
}
|
||||
}
|
||||
|
||||
static recDevice *
|
||||
FreeDevice(recDevice *removeDevice)
|
||||
{
|
||||
recDevice *pDeviceNext = NULL;
|
||||
if (removeDevice) {
|
||||
/* save next device prior to disposing of this device */
|
||||
pDeviceNext = removeDevice->pNext;
|
||||
|
||||
if ( gpDeviceList == removeDevice ) {
|
||||
gpDeviceList = pDeviceNext;
|
||||
} else {
|
||||
recDevice *device = gpDeviceList;
|
||||
while (device->pNext != removeDevice) {
|
||||
device = device->pNext;
|
||||
}
|
||||
device->pNext = pDeviceNext;
|
||||
}
|
||||
removeDevice->pNext = NULL;
|
||||
|
||||
/* free element lists */
|
||||
FreeElementList(removeDevice->firstAxis);
|
||||
FreeElementList(removeDevice->firstButton);
|
||||
FreeElementList(removeDevice->firstHat);
|
||||
|
||||
SDL_free(removeDevice);
|
||||
}
|
||||
return pDeviceNext;
|
||||
}
|
||||
|
||||
static SInt32
|
||||
GetHIDElementState(recDevice *pDevice, recElement *pElement)
|
||||
{
|
||||
SInt32 value = 0;
|
||||
|
||||
if (pDevice && pElement) {
|
||||
IOHIDValueRef valueRef;
|
||||
if (IOHIDDeviceGetValue(pDevice->deviceRef, pElement->elementRef, &valueRef) == kIOReturnSuccess) {
|
||||
value = (SInt32) IOHIDValueGetIntegerValue(valueRef);
|
||||
|
||||
/* record min and max for auto calibration */
|
||||
if (value < pElement->minReport) {
|
||||
pElement->minReport = value;
|
||||
}
|
||||
if (value > pElement->maxReport) {
|
||||
pElement->maxReport = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static SInt32
|
||||
GetHIDScaledCalibratedState(recDevice * pDevice, recElement * pElement, SInt32 min, SInt32 max)
|
||||
{
|
||||
const float deviceScale = max - min;
|
||||
const float readScale = pElement->maxReport - pElement->minReport;
|
||||
const SInt32 value = GetHIDElementState(pDevice, pElement);
|
||||
if (readScale == 0) {
|
||||
return value; /* no scaling at all */
|
||||
}
|
||||
return ((value - pElement->minReport) * deviceScale / readScale) + min;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
|
||||
{
|
||||
recDevice *device = (recDevice *) ctx;
|
||||
device->removed = 1;
|
||||
#if SDL_HAPTIC_IOKIT
|
||||
MacHaptic_MaybeRemoveDevice(device->ffservice);
|
||||
#endif
|
||||
s_bDeviceRemoved = SDL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void AddHIDElement(const void *value, void *parameter);
|
||||
|
||||
/* Call AddHIDElement() on all elements in an array of IOHIDElementRefs */
|
||||
static void
|
||||
AddHIDElements(CFArrayRef array, recDevice *pDevice)
|
||||
{
|
||||
const CFRange range = { 0, CFArrayGetCount(array) };
|
||||
CFArrayApplyFunction(array, range, AddHIDElement, pDevice);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
ElementAlreadyAdded(const IOHIDElementCookie cookie, const recElement *listitem) {
|
||||
while (listitem) {
|
||||
if (listitem->cookie == cookie) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
listitem = listitem->pNext;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* See if we care about this HID element, and if so, note it in our recDevice. */
|
||||
static void
|
||||
AddHIDElement(const void *value, void *parameter)
|
||||
{
|
||||
recDevice *pDevice = (recDevice *) parameter;
|
||||
IOHIDElementRef refElement = (IOHIDElementRef) value;
|
||||
const CFTypeID elementTypeID = refElement ? CFGetTypeID(refElement) : 0;
|
||||
|
||||
if (refElement && (elementTypeID == IOHIDElementGetTypeID())) {
|
||||
const IOHIDElementCookie cookie = IOHIDElementGetCookie(refElement);
|
||||
const uint32_t usagePage = IOHIDElementGetUsagePage(refElement);
|
||||
const uint32_t usage = IOHIDElementGetUsage(refElement);
|
||||
recElement *element = NULL;
|
||||
recElement **headElement = NULL;
|
||||
|
||||
/* look at types of interest */
|
||||
switch (IOHIDElementGetType(refElement)) {
|
||||
case kIOHIDElementTypeInput_Misc:
|
||||
case kIOHIDElementTypeInput_Button:
|
||||
case kIOHIDElementTypeInput_Axis: {
|
||||
switch (usagePage) { /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */
|
||||
case kHIDPage_GenericDesktop:
|
||||
switch (usage) {
|
||||
case kHIDUsage_GD_X:
|
||||
case kHIDUsage_GD_Y:
|
||||
case kHIDUsage_GD_Z:
|
||||
case kHIDUsage_GD_Rx:
|
||||
case kHIDUsage_GD_Ry:
|
||||
case kHIDUsage_GD_Rz:
|
||||
case kHIDUsage_GD_Slider:
|
||||
case kHIDUsage_GD_Dial:
|
||||
case kHIDUsage_GD_Wheel:
|
||||
if (!ElementAlreadyAdded(cookie, pDevice->firstAxis)) {
|
||||
element = (recElement *) SDL_calloc(1, sizeof (recElement));
|
||||
if (element) {
|
||||
pDevice->axes++;
|
||||
headElement = &(pDevice->firstAxis);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kHIDUsage_GD_Hatswitch:
|
||||
if (!ElementAlreadyAdded(cookie, pDevice->firstHat)) {
|
||||
element = (recElement *) SDL_calloc(1, sizeof (recElement));
|
||||
if (element) {
|
||||
pDevice->hats++;
|
||||
headElement = &(pDevice->firstHat);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kHIDPage_Simulation:
|
||||
switch (usage) {
|
||||
case kHIDUsage_Sim_Rudder:
|
||||
case kHIDUsage_Sim_Throttle:
|
||||
if (!ElementAlreadyAdded(cookie, pDevice->firstAxis)) {
|
||||
element = (recElement *) SDL_calloc(1, sizeof (recElement));
|
||||
if (element) {
|
||||
pDevice->axes++;
|
||||
headElement = &(pDevice->firstAxis);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kHIDPage_Button:
|
||||
if (!ElementAlreadyAdded(cookie, pDevice->firstButton)) {
|
||||
element = (recElement *) SDL_calloc(1, sizeof (recElement));
|
||||
if (element) {
|
||||
pDevice->buttons++;
|
||||
headElement = &(pDevice->firstButton);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kIOHIDElementTypeCollection: {
|
||||
CFArrayRef array = IOHIDElementGetChildren(refElement);
|
||||
if (array) {
|
||||
AddHIDElements(array, pDevice);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (element && headElement) { /* add to list */
|
||||
recElement *elementPrevious = NULL;
|
||||
recElement *elementCurrent = *headElement;
|
||||
while (elementCurrent && usage >= elementCurrent->usage) {
|
||||
elementPrevious = elementCurrent;
|
||||
elementCurrent = elementCurrent->pNext;
|
||||
}
|
||||
if (elementPrevious) {
|
||||
elementPrevious->pNext = element;
|
||||
} else {
|
||||
*headElement = element;
|
||||
}
|
||||
|
||||
element->elementRef = refElement;
|
||||
element->usagePage = usagePage;
|
||||
element->usage = usage;
|
||||
element->pNext = elementCurrent;
|
||||
|
||||
element->minReport = element->min = (SInt32) IOHIDElementGetLogicalMin(refElement);
|
||||
element->maxReport = element->max = (SInt32) IOHIDElementGetLogicalMax(refElement);
|
||||
element->cookie = IOHIDElementGetCookie(refElement);
|
||||
|
||||
pDevice->elements++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
||||
{
|
||||
Uint32 *guid32 = NULL;
|
||||
CFTypeRef refCF = NULL;
|
||||
CFArrayRef array = NULL;
|
||||
|
||||
/* get usage page and usage */
|
||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDPrimaryUsagePageKey));
|
||||
if (refCF) {
|
||||
CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->usagePage);
|
||||
}
|
||||
if (pDevice->usagePage != kHIDPage_GenericDesktop) {
|
||||
return SDL_FALSE; /* Filter device list to non-keyboard/mouse stuff */
|
||||
}
|
||||
|
||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDPrimaryUsageKey));
|
||||
if (refCF) {
|
||||
CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->usage);
|
||||
}
|
||||
|
||||
if ((pDevice->usage != kHIDUsage_GD_Joystick &&
|
||||
pDevice->usage != kHIDUsage_GD_GamePad &&
|
||||
pDevice->usage != kHIDUsage_GD_MultiAxisController)) {
|
||||
return SDL_FALSE; /* Filter device list to non-keyboard/mouse stuff */
|
||||
}
|
||||
|
||||
pDevice->deviceRef = hidDevice;
|
||||
|
||||
/* get device name */
|
||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductKey));
|
||||
if (!refCF) {
|
||||
/* Maybe we can't get "AwesomeJoystick2000", but we can get "Logitech"? */
|
||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDManufacturerKey));
|
||||
}
|
||||
if ((!refCF) || (!CFStringGetCString(refCF, pDevice->product, sizeof (pDevice->product), kCFStringEncodingUTF8))) {
|
||||
SDL_strlcpy(pDevice->product, "Unidentified joystick", sizeof (pDevice->product));
|
||||
}
|
||||
|
||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVendorIDKey));
|
||||
if (refCF) {
|
||||
CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->guid.data[0]);
|
||||
}
|
||||
|
||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductIDKey));
|
||||
if (refCF) {
|
||||
CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->guid.data[8]);
|
||||
}
|
||||
|
||||
/* Check to make sure we have a vendor and product ID
|
||||
If we don't, use the same algorithm as the Linux code for Bluetooth devices */
|
||||
guid32 = (Uint32*)pDevice->guid.data;
|
||||
if (!guid32[0] && !guid32[1]) {
|
||||
/* If we don't have a vendor and product ID this is probably a Bluetooth device */
|
||||
const Uint16 BUS_BLUETOOTH = 0x05;
|
||||
Uint16 *guid16 = (Uint16 *)guid32;
|
||||
*guid16++ = BUS_BLUETOOTH;
|
||||
*guid16++ = 0;
|
||||
SDL_strlcpy((char*)guid16, pDevice->product, sizeof(pDevice->guid.data) - 4);
|
||||
}
|
||||
|
||||
array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);
|
||||
if (array) {
|
||||
AddHIDElements(array, pDevice);
|
||||
CFRelease(array);
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef ioHIDDeviceObject)
|
||||
{
|
||||
if (res != kIOReturnSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
recDevice *device = (recDevice *) SDL_calloc(1, sizeof(recDevice));
|
||||
|
||||
if (!device) {
|
||||
SDL_OutOfMemory();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetDeviceInfo(ioHIDDeviceObject, device)) {
|
||||
SDL_free(device);
|
||||
return; /* not a device we care about, probably. */
|
||||
}
|
||||
|
||||
/* Get notified when this device is disconnected. */
|
||||
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
|
||||
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
|
||||
/* Allocate an instance ID for this device */
|
||||
device->instance_id = ++s_joystick_instance_id;
|
||||
|
||||
/* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */
|
||||
if (IOHIDDeviceGetService != NULL) { /* weak reference: available in 10.6 and later. */
|
||||
const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject);
|
||||
if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) {
|
||||
device->ffservice = ioservice;
|
||||
#if SDL_HAPTIC_IOKIT
|
||||
MacHaptic_MaybeAddDevice(ioservice);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
device->send_open_event = 1;
|
||||
s_bDeviceAdded = SDL_TRUE;
|
||||
|
||||
/* Add device to the end of the list */
|
||||
if ( !gpDeviceList )
|
||||
{
|
||||
gpDeviceList = device;
|
||||
}
|
||||
else
|
||||
{
|
||||
recDevice *curdevice;
|
||||
|
||||
curdevice = gpDeviceList;
|
||||
while ( curdevice->pNext )
|
||||
{
|
||||
curdevice = curdevice->pNext;
|
||||
}
|
||||
curdevice->pNext = device;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
ConfigHIDManager(CFArrayRef matchingArray)
|
||||
{
|
||||
CFRunLoopRef runloop = CFRunLoopGetCurrent();
|
||||
|
||||
/* Run in a custom RunLoop mode just while initializing,
|
||||
so we can detect sticks without messing with everything else. */
|
||||
CFStringRef tempRunLoopMode = CFSTR("SDLJoystickInit");
|
||||
|
||||
if (IOHIDManagerOpen(hidman, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(hidman, runloop, tempRunLoopMode);
|
||||
IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
|
||||
|
||||
while (CFRunLoopRunInMode(tempRunLoopMode,0,TRUE)==kCFRunLoopRunHandledSource) {
|
||||
/* no-op. Callback fires once per existing device. */
|
||||
}
|
||||
|
||||
/* Put this in the normal RunLoop mode now, for future hotplug events. */
|
||||
IOHIDManagerUnscheduleFromRunLoop(hidman, runloop, tempRunLoopMode);
|
||||
IOHIDManagerScheduleWithRunLoop(hidman, runloop, kCFRunLoopDefaultMode);
|
||||
|
||||
return SDL_TRUE; /* good to go. */
|
||||
}
|
||||
|
||||
|
||||
static CFDictionaryRef
|
||||
CreateHIDDeviceMatchDictionary(const UInt32 page, const UInt32 usage, int *okay)
|
||||
{
|
||||
CFDictionaryRef retval = NULL;
|
||||
CFNumberRef pageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page);
|
||||
CFNumberRef usageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
|
||||
const void *keys[2] = { (void *) CFSTR(kIOHIDDeviceUsagePageKey), (void *) CFSTR(kIOHIDDeviceUsageKey) };
|
||||
const void *vals[2] = { (void *) pageNumRef, (void *) usageNumRef };
|
||||
|
||||
if (pageNumRef && usageNumRef) {
|
||||
retval = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
}
|
||||
|
||||
if (pageNumRef) {
|
||||
CFRelease(pageNumRef);
|
||||
}
|
||||
if (usageNumRef) {
|
||||
CFRelease(usageNumRef);
|
||||
}
|
||||
|
||||
if (!retval) {
|
||||
*okay = 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
CreateHIDManager(void)
|
||||
{
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
int okay = 1;
|
||||
const void *vals[] = {
|
||||
(void *) CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, &okay),
|
||||
(void *) CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, &okay),
|
||||
(void *) CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController, &okay),
|
||||
};
|
||||
const size_t numElements = SDL_arraysize(vals);
|
||||
CFArrayRef array = okay ? CFArrayCreate(kCFAllocatorDefault, vals, numElements, &kCFTypeArrayCallBacks) : NULL;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < numElements; i++) {
|
||||
if (vals[i]) {
|
||||
CFRelease((CFTypeRef) vals[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (array) {
|
||||
hidman = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
if (hidman != NULL) {
|
||||
retval = ConfigHIDManager(array);
|
||||
}
|
||||
CFRelease(array);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
if (gpDeviceList) {
|
||||
return SDL_SetError("Joystick: Device list already inited.");
|
||||
}
|
||||
|
||||
if (!CreateHIDManager()) {
|
||||
return SDL_SetError("Joystick: Couldn't initialize HID Manager");
|
||||
}
|
||||
|
||||
return SDL_SYS_NumJoysticks();
|
||||
}
|
||||
|
||||
/* Function to return the number of joystick devices plugged in right now */
|
||||
int
|
||||
SDL_SYS_NumJoysticks()
|
||||
{
|
||||
recDevice *device = gpDeviceList;
|
||||
int nJoySticks = 0;
|
||||
|
||||
while (device) {
|
||||
if (!device->removed) {
|
||||
nJoySticks++;
|
||||
}
|
||||
device = device->pNext;
|
||||
}
|
||||
|
||||
return nJoySticks;
|
||||
}
|
||||
|
||||
/* Function to cause any queued joystick insertions to be processed
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickDetect()
|
||||
{
|
||||
if (s_bDeviceAdded || s_bDeviceRemoved) {
|
||||
recDevice *device = gpDeviceList;
|
||||
s_bDeviceAdded = SDL_FALSE;
|
||||
s_bDeviceRemoved = SDL_FALSE;
|
||||
int device_index = 0;
|
||||
/* send notifications */
|
||||
while (device) {
|
||||
if (device->send_open_event) {
|
||||
device->send_open_event = 0;
|
||||
/* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceAdded()? */
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = device_index;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
}
|
||||
|
||||
if (device->removed) {
|
||||
const int instance_id = device->instance_id;
|
||||
device = FreeDevice(device);
|
||||
|
||||
/* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceRemoved()? */
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = instance_id;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
} else {
|
||||
device = device->pNext;
|
||||
device_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return s_bDeviceAdded || s_bDeviceRemoved;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
recDevice *device = gpDeviceList;
|
||||
|
||||
while (device_index-- > 0) {
|
||||
device = device->pNext;
|
||||
}
|
||||
|
||||
return device->product;
|
||||
}
|
||||
|
||||
/* Function to return the instance id of the joystick at device_index
|
||||
*/
|
||||
SDL_JoystickID
|
||||
SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
recDevice *device = gpDeviceList;
|
||||
int index;
|
||||
|
||||
for (index = device_index; index > 0; index--) {
|
||||
device = device->pNext;
|
||||
}
|
||||
|
||||
return device->instance_id;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
recDevice *device = gpDeviceList;
|
||||
int index;
|
||||
|
||||
for (index = device_index; index > 0; index--) {
|
||||
device = device->pNext;
|
||||
}
|
||||
|
||||
joystick->instance_id = device->instance_id;
|
||||
joystick->hwdata = device;
|
||||
joystick->name = device->product;
|
||||
|
||||
joystick->naxes = device->axes;
|
||||
joystick->nhats = device->hats;
|
||||
joystick->nballs = 0;
|
||||
joystick->nbuttons = device->buttons;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to query if the joystick is currently attached
|
||||
* It returns 1 if attached, 0 otherwise.
|
||||
*/
|
||||
SDL_bool
|
||||
SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
|
||||
{
|
||||
recDevice *device = gpDeviceList;
|
||||
|
||||
while (device) {
|
||||
if (joystick->instance_id == device->instance_id) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
device = device->pNext;
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
recDevice *device = joystick->hwdata;
|
||||
recElement *element;
|
||||
SInt32 value, range;
|
||||
int i;
|
||||
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->removed) { /* device was unplugged; ignore it. */
|
||||
joystick->closed = 1;
|
||||
joystick->uncentered = 1;
|
||||
joystick->hwdata = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
element = device->firstAxis;
|
||||
i = 0;
|
||||
while (element) {
|
||||
value = GetHIDScaledCalibratedState(device, element, -32768, 32767);
|
||||
if (value != joystick->axes[i]) {
|
||||
SDL_PrivateJoystickAxis(joystick, i, value);
|
||||
}
|
||||
element = element->pNext;
|
||||
++i;
|
||||
}
|
||||
|
||||
element = device->firstButton;
|
||||
i = 0;
|
||||
while (element) {
|
||||
value = GetHIDElementState(device, element);
|
||||
if (value > 1) { /* handle pressure-sensitive buttons */
|
||||
value = 1;
|
||||
}
|
||||
if (value != joystick->buttons[i]) {
|
||||
SDL_PrivateJoystickButton(joystick, i, value);
|
||||
}
|
||||
element = element->pNext;
|
||||
++i;
|
||||
}
|
||||
|
||||
element = device->firstHat;
|
||||
i = 0;
|
||||
while (element) {
|
||||
Uint8 pos = 0;
|
||||
|
||||
range = (element->max - element->min + 1);
|
||||
value = GetHIDElementState(device, element) - element->min;
|
||||
if (range == 4) { /* 4 position hatswitch - scale up value */
|
||||
value *= 2;
|
||||
} else if (range != 8) { /* Neither a 4 nor 8 positions - fall back to default position (centered) */
|
||||
value = -1;
|
||||
}
|
||||
switch (value) {
|
||||
case 0:
|
||||
pos = SDL_HAT_UP;
|
||||
break;
|
||||
case 1:
|
||||
pos = SDL_HAT_RIGHTUP;
|
||||
break;
|
||||
case 2:
|
||||
pos = SDL_HAT_RIGHT;
|
||||
break;
|
||||
case 3:
|
||||
pos = SDL_HAT_RIGHTDOWN;
|
||||
break;
|
||||
case 4:
|
||||
pos = SDL_HAT_DOWN;
|
||||
break;
|
||||
case 5:
|
||||
pos = SDL_HAT_LEFTDOWN;
|
||||
break;
|
||||
case 6:
|
||||
pos = SDL_HAT_LEFT;
|
||||
break;
|
||||
case 7:
|
||||
pos = SDL_HAT_LEFTUP;
|
||||
break;
|
||||
default:
|
||||
/* Every other value is mapped to center. We do that because some
|
||||
* joysticks use 8 and some 15 for this value, and apparently
|
||||
* there are even more variants out there - so we try to be generous.
|
||||
*/
|
||||
pos = SDL_HAT_CENTERED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos != joystick->hats[i]) {
|
||||
SDL_PrivateJoystickHat(joystick, i, pos);
|
||||
}
|
||||
|
||||
element = element->pNext;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
joystick->closed = 1;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
while (FreeDevice(gpDeviceList)) {
|
||||
/* spin */
|
||||
}
|
||||
|
||||
if (hidman) {
|
||||
IOHIDManagerClose(hidman, kIOHIDOptionsTypeNone);
|
||||
CFRelease(hidman);
|
||||
hidman = NULL;
|
||||
}
|
||||
|
||||
s_bDeviceAdded = s_bDeviceRemoved = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
recDevice *device = gpDeviceList;
|
||||
int index;
|
||||
|
||||
for (index = device_index; index > 0; index--) {
|
||||
device = device->pNext;
|
||||
}
|
||||
|
||||
return device->guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
|
||||
{
|
||||
return joystick->hwdata->guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_IOKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
73
src/joystick/darwin/SDL_sysjoystick_c.h
Normal file
73
src/joystick/darwin/SDL_sysjoystick_c.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_JOYSTICK_IOKIT_H
|
||||
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
struct recElement
|
||||
{
|
||||
IOHIDElementRef elementRef;
|
||||
IOHIDElementCookie cookie;
|
||||
uint32_t usagePage, usage; /* HID usage */
|
||||
SInt32 min; /* reported min value possible */
|
||||
SInt32 max; /* reported max value possible */
|
||||
|
||||
/* runtime variables used for auto-calibration */
|
||||
SInt32 minReport; /* min returned value */
|
||||
SInt32 maxReport; /* max returned value */
|
||||
|
||||
struct recElement *pNext; /* next element in list */
|
||||
};
|
||||
typedef struct recElement recElement;
|
||||
|
||||
struct joystick_hwdata
|
||||
{
|
||||
IOHIDDeviceRef deviceRef; /* HIDManager device handle */
|
||||
io_service_t ffservice; /* Interface for force feedback, 0 = no ff */
|
||||
|
||||
char product[256]; /* name of product */
|
||||
uint32_t usage; /* usage page from IOUSBHID Parser.h which defines general usage */
|
||||
uint32_t usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */
|
||||
|
||||
int axes; /* number of axis (calculated, not reported by device) */
|
||||
int buttons; /* number of buttons (calculated, not reported by device) */
|
||||
int hats; /* number of hat switches (calculated, not reported by device) */
|
||||
int 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-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
|
||||
|
||||
/* This is the dummy implementation of 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: */
|
||||
281
src/joystick/haiku/SDL_haikujoystick.cc
Normal file
281
src/joystick/haiku/SDL_haikujoystick.cc
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_HAIKU
|
||||
|
||||
/* This is the Haiku implementation of the SDL joystick API */
|
||||
|
||||
#include <os/support/String.h>
|
||||
#include <os/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;
|
||||
SDL_free(joystick->hwdata->new_hats);
|
||||
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_HAIKU */
|
||||
|
||||
/* 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-2014 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-2014 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-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
/* This is the iOS implementation of 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: */
|
||||
894
src/joystick/linux/SDL_sysjoystick.c
Normal file
894
src/joystick/linux/SDL_sysjoystick.c
Normal file
@@ -0,0 +1,894 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_LINUX
|
||||
|
||||
#ifndef SDL_INPUT_LINUXEV
|
||||
#error SDL now requires a Linux 2.4+ kernel with /dev/input/event support.
|
||||
#endif
|
||||
|
||||
/* This is the Linux implementation of the SDL joystick API */
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <limits.h> /* For the definition of PATH_MAX */
|
||||
#include <linux/joystick.h>
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_endian.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "SDL_sysjoystick_c.h"
|
||||
|
||||
/* !!! FIXME: move this somewhere else. */
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
/* This isn't defined in older Linux kernel headers */
|
||||
#ifndef SYN_DROPPED
|
||||
#define SYN_DROPPED 3
|
||||
#endif
|
||||
|
||||
#include "../../core/linux/SDL_udev.h"
|
||||
|
||||
static int MaybeAddDevice(const char *path);
|
||||
#if SDL_USE_LIBUDEV
|
||||
static int MaybeRemoveDevice(const char *path);
|
||||
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
|
||||
/* A linked list of available joysticks */
|
||||
typedef struct SDL_joylist_item
|
||||
{
|
||||
int device_instance;
|
||||
char *path; /* "/dev/input/event2" or whatever */
|
||||
char *name; /* "SideWinder 3D Pro" or whatever */
|
||||
SDL_JoystickGUID guid;
|
||||
dev_t devnum;
|
||||
struct joystick_hwdata *hwdata;
|
||||
struct SDL_joylist_item *next;
|
||||
} SDL_joylist_item;
|
||||
|
||||
static SDL_joylist_item *SDL_joylist = NULL;
|
||||
static SDL_joylist_item *SDL_joylist_tail = NULL;
|
||||
static int numjoysticks = 0;
|
||||
static int instance_counter = 0;
|
||||
|
||||
#define test_bit(nr, addr) \
|
||||
(((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
|
||||
#define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
|
||||
|
||||
static int
|
||||
IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *guid)
|
||||
{
|
||||
struct input_id inpid;
|
||||
Uint16 *guid16 = (Uint16 *) ((char *) &guid->data);
|
||||
|
||||
#if !SDL_USE_LIBUDEV
|
||||
/* When udev is enabled we only get joystick devices here, so there's no need to test them */
|
||||
unsigned long evbit[NBITS(EV_MAX)] = { 0 };
|
||||
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
|
||||
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
|
||||
|
||||
if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
|
||||
(ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
|
||||
(ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
|
||||
test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit))) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ioctl(fd, EVIOCGNAME(namebuflen), namebuf) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
printf("Joystick: %s, bustype = %d, vendor = 0x%x, product = 0x%x, version = %d\n", namebuf, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
|
||||
#endif
|
||||
|
||||
SDL_memset(guid->data, 0, sizeof(guid->data));
|
||||
|
||||
/* We only need 16 bits for each of these; space them out to fill 128. */
|
||||
/* Byteswap so devices get same GUID on little/big endian platforms. */
|
||||
*(guid16++) = SDL_SwapLE16(inpid.bustype);
|
||||
*(guid16++) = 0;
|
||||
|
||||
if (inpid.vendor && inpid.product && inpid.version) {
|
||||
*(guid16++) = SDL_SwapLE16(inpid.vendor);
|
||||
*(guid16++) = 0;
|
||||
*(guid16++) = SDL_SwapLE16(inpid.product);
|
||||
*(guid16++) = 0;
|
||||
*(guid16++) = SDL_SwapLE16(inpid.version);
|
||||
*(guid16++) = 0;
|
||||
} else {
|
||||
SDL_strlcpy((char*)guid16, namebuf, sizeof(guid->data) - 4);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
|
||||
{
|
||||
if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch( udev_type )
|
||||
{
|
||||
case SDL_UDEV_DEVICEADDED:
|
||||
MaybeAddDevice(devpath);
|
||||
break;
|
||||
|
||||
case SDL_UDEV_DEVICEREMOVED:
|
||||
MaybeRemoveDevice(devpath);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
|
||||
/* !!! FIXME: I would love to dump this code and use libudev instead. */
|
||||
static int
|
||||
MaybeAddDevice(const char *path)
|
||||
{
|
||||
struct stat sb;
|
||||
int fd = -1;
|
||||
int isstick = 0;
|
||||
char namebuf[128];
|
||||
SDL_JoystickGUID guid;
|
||||
SDL_joylist_item *item;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
if (path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stat(path, &sb) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check to make sure it's not already in list. */
|
||||
for (item = SDL_joylist; item != NULL; item = item->next) {
|
||||
if (sb.st_rdev == item->devnum) {
|
||||
return -1; /* already have this one */
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_INPUT_EVENTS
|
||||
printf("Checking %s\n", path);
|
||||
#endif
|
||||
|
||||
isstick = IsJoystick(fd, namebuf, sizeof (namebuf), &guid);
|
||||
close(fd);
|
||||
if (!isstick) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_zerop(item);
|
||||
item->devnum = sb.st_rdev;
|
||||
item->path = SDL_strdup(path);
|
||||
item->name = SDL_strdup(namebuf);
|
||||
item->guid = guid;
|
||||
|
||||
if ( (item->path == NULL) || (item->name == NULL) ) {
|
||||
SDL_free(item->path);
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
item->device_instance = instance_counter++;
|
||||
if (SDL_joylist_tail == NULL) {
|
||||
SDL_joylist = SDL_joylist_tail = item;
|
||||
} else {
|
||||
SDL_joylist_tail->next = item;
|
||||
SDL_joylist_tail = item;
|
||||
}
|
||||
|
||||
/* Need to increment the joystick count before we post the event */
|
||||
++numjoysticks;
|
||||
|
||||
/* !!! FIXME: Move this to an SDL_PrivateJoyDeviceAdded() function? */
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = (numjoysticks - 1);
|
||||
if ( (SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
/* !!! FIXME: I would love to dump this code and use libudev instead. */
|
||||
static int
|
||||
MaybeRemoveDevice(const char *path)
|
||||
{
|
||||
SDL_joylist_item *item;
|
||||
SDL_joylist_item *prev = NULL;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
if (path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (item = SDL_joylist; item != NULL; item = item->next) {
|
||||
/* found it, remove it. */
|
||||
if (SDL_strcmp(path, item->path) == 0) {
|
||||
const int retval = item->device_instance;
|
||||
if (item->hwdata) {
|
||||
item->hwdata->item = NULL;
|
||||
}
|
||||
if (prev != NULL) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
SDL_assert(SDL_joylist == item);
|
||||
SDL_joylist = item->next;
|
||||
}
|
||||
if (item == SDL_joylist_tail) {
|
||||
SDL_joylist_tail = prev;
|
||||
}
|
||||
|
||||
/* Need to decrement the joystick count before we post the event */
|
||||
--numjoysticks;
|
||||
|
||||
/* !!! FIXME: Move this to an SDL_PrivateJoyDeviceRemoved() function? */
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = item->device_instance;
|
||||
if ( (SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
SDL_free(item->path);
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
return retval;
|
||||
}
|
||||
prev = item;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
JoystickInitWithoutUdev(void)
|
||||
{
|
||||
int i;
|
||||
char path[PATH_MAX];
|
||||
|
||||
/* !!! FIXME: only finds sticks if they're called /dev/input/event[0..31] */
|
||||
/* !!! FIXME: we could at least readdir() through /dev/input...? */
|
||||
/* !!! FIXME: (or delete this and rely on libudev?) */
|
||||
for (i = 0; i < 32; i++) {
|
||||
SDL_snprintf(path, SDL_arraysize(path), "/dev/input/event%d", i);
|
||||
MaybeAddDevice(path);
|
||||
}
|
||||
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
static int
|
||||
JoystickInitWithUdev(void)
|
||||
{
|
||||
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
return SDL_SetError("Could not initialize UDEV");
|
||||
}
|
||||
|
||||
/* Set up the udev callback */
|
||||
if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("Could not set up joystick <-> udev callback");
|
||||
}
|
||||
|
||||
/* Force a scan to build the initial device list */
|
||||
SDL_UDEV_Scan();
|
||||
|
||||
return numjoysticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
/* First see if the user specified one or more joysticks to use */
|
||||
if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
|
||||
char *envcopy, *envpath, *delim;
|
||||
envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE"));
|
||||
envpath = envcopy;
|
||||
while (envpath != NULL) {
|
||||
delim = SDL_strchr(envpath, ':');
|
||||
if (delim != NULL) {
|
||||
*delim++ = '\0';
|
||||
}
|
||||
MaybeAddDevice(envpath);
|
||||
envpath = delim;
|
||||
}
|
||||
SDL_free(envcopy);
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
return JoystickInitWithUdev();
|
||||
#endif
|
||||
|
||||
return JoystickInitWithoutUdev();
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
#if SDL_USE_LIBUDEV
|
||||
SDL_UDEV_Poll();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
#if SDL_USE_LIBUDEV
|
||||
return SDL_TRUE;
|
||||
#endif
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static SDL_joylist_item *
|
||||
JoystickByDevIndex(int device_index)
|
||||
{
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
|
||||
if ((device_index < 0) || (device_index >= numjoysticks)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (device_index > 0) {
|
||||
SDL_assert(item != NULL);
|
||||
device_index--;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return JoystickByDevIndex(device_index)->name;
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return JoystickByDevIndex(device_index)->device_instance;
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_hatdata(SDL_Joystick * joystick)
|
||||
{
|
||||
int i;
|
||||
|
||||
joystick->hwdata->hats =
|
||||
(struct hwdata_hat *) SDL_malloc(joystick->nhats *
|
||||
sizeof(struct hwdata_hat));
|
||||
if (joystick->hwdata->hats == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
for (i = 0; i < joystick->nhats; ++i) {
|
||||
joystick->hwdata->hats[i].axis[0] = 1;
|
||||
joystick->hwdata->hats[i].axis[1] = 1;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_balldata(SDL_Joystick * joystick)
|
||||
{
|
||||
int i;
|
||||
|
||||
joystick->hwdata->balls =
|
||||
(struct hwdata_ball *) SDL_malloc(joystick->nballs *
|
||||
sizeof(struct hwdata_ball));
|
||||
if (joystick->hwdata->balls == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
for (i = 0; i < joystick->nballs; ++i) {
|
||||
joystick->hwdata->balls[i].axis[0] = 0;
|
||||
joystick->hwdata->balls[i].axis[1] = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ConfigJoystick(SDL_Joystick * joystick, int fd)
|
||||
{
|
||||
int i, t;
|
||||
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
|
||||
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
|
||||
unsigned long relbit[NBITS(REL_MAX)] = { 0 };
|
||||
|
||||
/* See if this device uses the new unified event API */
|
||||
if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
|
||||
(ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
|
||||
(ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
|
||||
|
||||
/* Get the number of buttons, axes, and other thingamajigs */
|
||||
for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
|
||||
if (test_bit(i, keybit)) {
|
||||
#ifdef DEBUG_INPUT_EVENTS
|
||||
printf("Joystick has button: 0x%x\n", i);
|
||||
#endif
|
||||
joystick->hwdata->key_map[i - BTN_MISC] = joystick->nbuttons;
|
||||
++joystick->nbuttons;
|
||||
}
|
||||
}
|
||||
for (i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
|
||||
if (test_bit(i, keybit)) {
|
||||
#ifdef DEBUG_INPUT_EVENTS
|
||||
printf("Joystick has button: 0x%x\n", i);
|
||||
#endif
|
||||
joystick->hwdata->key_map[i - BTN_MISC] = joystick->nbuttons;
|
||||
++joystick->nbuttons;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ABS_MISC; ++i) {
|
||||
/* Skip hats */
|
||||
if (i == ABS_HAT0X) {
|
||||
i = ABS_HAT3Y;
|
||||
continue;
|
||||
}
|
||||
if (test_bit(i, absbit)) {
|
||||
struct input_absinfo absinfo;
|
||||
|
||||
if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_INPUT_EVENTS
|
||||
printf("Joystick has absolute axis: 0x%.2x\n", i);
|
||||
printf("Values = { %d, %d, %d, %d, %d }\n",
|
||||
absinfo.value, absinfo.minimum, absinfo.maximum,
|
||||
absinfo.fuzz, absinfo.flat);
|
||||
#endif /* DEBUG_INPUT_EVENTS */
|
||||
joystick->hwdata->abs_map[i] = joystick->naxes;
|
||||
if (absinfo.minimum == absinfo.maximum) {
|
||||
joystick->hwdata->abs_correct[i].used = 0;
|
||||
} else {
|
||||
joystick->hwdata->abs_correct[i].used = 1;
|
||||
joystick->hwdata->abs_correct[i].coef[0] =
|
||||
(absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
|
||||
joystick->hwdata->abs_correct[i].coef[1] =
|
||||
(absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
|
||||
t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
|
||||
if (t != 0) {
|
||||
joystick->hwdata->abs_correct[i].coef[2] =
|
||||
(1 << 28) / t;
|
||||
} else {
|
||||
joystick->hwdata->abs_correct[i].coef[2] = 0;
|
||||
}
|
||||
}
|
||||
++joystick->naxes;
|
||||
}
|
||||
}
|
||||
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
|
||||
if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
|
||||
struct input_absinfo absinfo;
|
||||
|
||||
if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_INPUT_EVENTS
|
||||
printf("Joystick has hat %d\n", (i - ABS_HAT0X) / 2);
|
||||
printf("Values = { %d, %d, %d, %d, %d }\n",
|
||||
absinfo.value, absinfo.minimum, absinfo.maximum,
|
||||
absinfo.fuzz, absinfo.flat);
|
||||
#endif /* DEBUG_INPUT_EVENTS */
|
||||
++joystick->nhats;
|
||||
}
|
||||
}
|
||||
if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
|
||||
++joystick->nballs;
|
||||
}
|
||||
|
||||
/* Allocate data to keep track of these thingamajigs */
|
||||
if (joystick->nhats > 0) {
|
||||
if (allocate_hatdata(joystick) < 0) {
|
||||
joystick->nhats = 0;
|
||||
}
|
||||
}
|
||||
if (joystick->nballs > 0) {
|
||||
if (allocate_balldata(joystick) < 0) {
|
||||
joystick->nballs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
SDL_joylist_item *item = JoystickByDevIndex(device_index);
|
||||
char *fname = NULL;
|
||||
int fd = -1;
|
||||
|
||||
if (item == NULL) {
|
||||
return SDL_SetError("No such device");
|
||||
}
|
||||
|
||||
fname = item->path;
|
||||
fd = open(fname, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
return SDL_SetError("Unable to open %s", fname);
|
||||
}
|
||||
|
||||
joystick->instance_id = item->device_instance;
|
||||
joystick->hwdata = (struct joystick_hwdata *)
|
||||
SDL_malloc(sizeof(*joystick->hwdata));
|
||||
if (joystick->hwdata == NULL) {
|
||||
close(fd);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
|
||||
joystick->hwdata->item = item;
|
||||
joystick->hwdata->guid = item->guid;
|
||||
joystick->hwdata->fd = fd;
|
||||
joystick->hwdata->fname = SDL_strdup(item->path);
|
||||
if (joystick->hwdata->fname == NULL) {
|
||||
SDL_free(joystick->hwdata);
|
||||
joystick->hwdata = NULL;
|
||||
close(fd);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
SDL_assert(item->hwdata == NULL);
|
||||
item->hwdata = joystick->hwdata;
|
||||
|
||||
/* Set the joystick to non-blocking read mode */
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
|
||||
/* Get the number of buttons and axes on the joystick */
|
||||
ConfigJoystick(joystick, fd);
|
||||
|
||||
/* mark joystick as fresh and ready */
|
||||
joystick->hwdata->fresh = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return !joystick->closed && (joystick->hwdata->item != NULL);
|
||||
}
|
||||
|
||||
static SDL_INLINE void
|
||||
HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
|
||||
{
|
||||
struct hwdata_hat *the_hat;
|
||||
const Uint8 position_map[3][3] = {
|
||||
{SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
|
||||
{SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
|
||||
{SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
|
||||
};
|
||||
|
||||
the_hat = &stick->hwdata->hats[hat];
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
} else if (value == 0) {
|
||||
value = 1;
|
||||
} else if (value > 0) {
|
||||
value = 2;
|
||||
}
|
||||
if (value != the_hat->axis[axis]) {
|
||||
the_hat->axis[axis] = value;
|
||||
SDL_PrivateJoystickHat(stick, hat,
|
||||
position_map[the_hat->
|
||||
axis[1]][the_hat->axis[0]]);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_INLINE void
|
||||
HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value)
|
||||
{
|
||||
stick->hwdata->balls[ball].axis[axis] += value;
|
||||
}
|
||||
|
||||
|
||||
static SDL_INLINE int
|
||||
AxisCorrect(SDL_Joystick * joystick, int which, int value)
|
||||
{
|
||||
struct axis_correct *correct;
|
||||
|
||||
correct = &joystick->hwdata->abs_correct[which];
|
||||
if (correct->used) {
|
||||
value *= 2;
|
||||
if (value > correct->coef[0]) {
|
||||
if (value < correct->coef[1]) {
|
||||
return 0;
|
||||
}
|
||||
value -= correct->coef[1];
|
||||
} else {
|
||||
value -= correct->coef[0];
|
||||
}
|
||||
value *= correct->coef[2];
|
||||
value >>= 13;
|
||||
}
|
||||
|
||||
/* Clamp and return */
|
||||
if (value < -32768)
|
||||
return -32768;
|
||||
if (value > 32767)
|
||||
return 32767;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static SDL_INLINE void
|
||||
PollAllValues(SDL_Joystick * joystick)
|
||||
{
|
||||
struct input_absinfo absinfo;
|
||||
int a, b = 0;
|
||||
|
||||
/* Poll all axis */
|
||||
for (a = ABS_X; b < ABS_MAX; a++) {
|
||||
switch (a) {
|
||||
case ABS_HAT0X:
|
||||
case ABS_HAT0Y:
|
||||
case ABS_HAT1X:
|
||||
case ABS_HAT1Y:
|
||||
case ABS_HAT2X:
|
||||
case ABS_HAT2Y:
|
||||
case ABS_HAT3X:
|
||||
case ABS_HAT3Y:
|
||||
/* ingore hats */
|
||||
break;
|
||||
default:
|
||||
if (joystick->hwdata->abs_correct[b].used) {
|
||||
if (ioctl(joystick->hwdata->fd, EVIOCGABS(a), &absinfo) >= 0) {
|
||||
absinfo.value = AxisCorrect(joystick, b, absinfo.value);
|
||||
|
||||
#ifdef DEBUG_INPUT_EVENTS
|
||||
printf("Joystick : Re-read Axis %d (%d) val= %d\n",
|
||||
joystick->hwdata->abs_map[b], a, absinfo.value);
|
||||
#endif
|
||||
SDL_PrivateJoystickAxis(joystick,
|
||||
joystick->hwdata->abs_map[b],
|
||||
absinfo.value);
|
||||
}
|
||||
}
|
||||
b++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_INLINE void
|
||||
HandleInputEvents(SDL_Joystick * joystick)
|
||||
{
|
||||
struct input_event events[32];
|
||||
int i, len;
|
||||
int code;
|
||||
|
||||
if (joystick->hwdata->fresh) {
|
||||
PollAllValues(joystick);
|
||||
joystick->hwdata->fresh = 0;
|
||||
}
|
||||
|
||||
while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
|
||||
len /= sizeof(events[0]);
|
||||
for (i = 0; i < len; ++i) {
|
||||
code = events[i].code;
|
||||
switch (events[i].type) {
|
||||
case EV_KEY:
|
||||
if (code >= BTN_MISC) {
|
||||
code -= BTN_MISC;
|
||||
SDL_PrivateJoystickButton(joystick,
|
||||
joystick->hwdata->key_map[code],
|
||||
events[i].value);
|
||||
}
|
||||
break;
|
||||
case EV_ABS:
|
||||
if (code >= ABS_MISC) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case ABS_HAT0X:
|
||||
case ABS_HAT0Y:
|
||||
case ABS_HAT1X:
|
||||
case ABS_HAT1Y:
|
||||
case ABS_HAT2X:
|
||||
case ABS_HAT2Y:
|
||||
case ABS_HAT3X:
|
||||
case ABS_HAT3Y:
|
||||
code -= ABS_HAT0X;
|
||||
HandleHat(joystick, code / 2, code % 2, events[i].value);
|
||||
break;
|
||||
default:
|
||||
events[i].value =
|
||||
AxisCorrect(joystick, code, events[i].value);
|
||||
SDL_PrivateJoystickAxis(joystick,
|
||||
joystick->hwdata->abs_map[code],
|
||||
events[i].value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EV_REL:
|
||||
switch (code) {
|
||||
case REL_X:
|
||||
case REL_Y:
|
||||
code -= REL_X;
|
||||
HandleBall(joystick, code / 2, code % 2, events[i].value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EV_SYN:
|
||||
switch (code) {
|
||||
case SYN_DROPPED :
|
||||
#ifdef DEBUG_INPUT_EVENTS
|
||||
printf("Event SYN_DROPPED detected\n");
|
||||
#endif
|
||||
PollAllValues(joystick);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
int i;
|
||||
|
||||
HandleInputEvents(joystick);
|
||||
|
||||
/* Deliver ball motion updates */
|
||||
for (i = 0; i < joystick->nballs; ++i) {
|
||||
int xrel, yrel;
|
||||
|
||||
xrel = joystick->hwdata->balls[i].axis[0];
|
||||
yrel = joystick->hwdata->balls[i].axis[1];
|
||||
if (xrel || yrel) {
|
||||
joystick->hwdata->balls[i].axis[0] = 0;
|
||||
joystick->hwdata->balls[i].axis[1] = 0;
|
||||
SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata) {
|
||||
close(joystick->hwdata->fd);
|
||||
if (joystick->hwdata->item) {
|
||||
joystick->hwdata->item->hwdata = NULL;
|
||||
}
|
||||
SDL_free(joystick->hwdata->hats);
|
||||
SDL_free(joystick->hwdata->balls);
|
||||
SDL_free(joystick->hwdata->fname);
|
||||
SDL_free(joystick->hwdata);
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
joystick->closed = 1;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
SDL_joylist_item *item = NULL;
|
||||
SDL_joylist_item *next = NULL;
|
||||
|
||||
for (item = SDL_joylist; item; item = next) {
|
||||
next = item->next;
|
||||
SDL_free(item->path);
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
}
|
||||
|
||||
SDL_joylist = SDL_joylist_tail = NULL;
|
||||
|
||||
numjoysticks = 0;
|
||||
instance_counter = 0;
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
SDL_UDEV_DelCallback(joystick_udev_callback);
|
||||
SDL_UDEV_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
return JoystickByDevIndex(device_index)->guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
return joystick->hwdata->guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_LINUX */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
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-2014 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-2014 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 PSP implementation of 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 SDL_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
|
||||
*/
|
||||
63
src/joystick/sort_controllers.py
Executable file
63
src/joystick/sort_controllers.py
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/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 not line.endswith(",\n") and not line.endswith("*/\n"):
|
||||
print "Warning: '%s' is missing a comma at the end of the line" % (line)
|
||||
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
|
||||
1683
src/joystick/windows/SDL_dxjoystick.c
Normal file
1683
src/joystick/windows/SDL_dxjoystick.c
Normal file
File diff suppressed because it is too large
Load Diff
150
src/joystick/windows/SDL_dxjoystick_c.h
Normal file
150
src/joystick/windows/SDL_dxjoystick_c.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#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>
|
||||
|
||||
|
||||
#ifndef XUSER_MAX_COUNT
|
||||
#define XUSER_MAX_COUNT 4
|
||||
#endif
|
||||
#ifndef XUSER_INDEX_ANY
|
||||
#define XUSER_INDEX_ANY 0x000000FF
|
||||
#endif
|
||||
#ifndef XINPUT_CAPS_FFB_SUPPORTED
|
||||
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
|
||||
#endif
|
||||
|
||||
|
||||
/* 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 XUSER_INDEX_ANY
|
||||
#define SDL_XINPUT_MAX_DEVICES XUSER_MAX_COUNT
|
||||
|
||||
#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 */
|
||||
475
src/joystick/windows/SDL_mmjoystick.c
Normal file
475
src/joystick/windows/SDL_mmjoystick.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_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"
|
||||
|
||||
#ifdef REGSTR_VAL_JOYOEMNAME
|
||||
#undef REGSTR_VAL_JOYOEMNAME
|
||||
#endif
|
||||
#define REGSTR_VAL_JOYOEMNAME "OEMName"
|
||||
|
||||
#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 JOYCAPSA 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;
|
||||
JOYCAPSA 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 = joyGetDevCapsA(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)
|
||||
{
|
||||
/* 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++) {
|
||||
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: */
|
||||
537
src/joystick/winrt/SDL_xinputjoystick.c
Normal file
537
src/joystick/winrt/SDL_xinputjoystick.c
Normal file
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_JOYSTICK_XINPUT
|
||||
|
||||
/* SDL_xinputjoystick.c implements an XInput-only joystick and game controller
|
||||
backend that is suitable for use on WinRT. SDL's DirectInput backend, also
|
||||
XInput-capable, was not used as DirectInput is not available on WinRT (or,
|
||||
at least, it isn't a public API). Some portions of this XInput backend
|
||||
may copy parts of the XInput-using code from the DirectInput backend.
|
||||
Refactoring the common parts into one location may be good to-do at some
|
||||
point.
|
||||
|
||||
TODO, WinRT: add hotplug support for XInput based game controllers
|
||||
*/
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "SDL_events.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Xinput.h>
|
||||
|
||||
struct joystick_hwdata {
|
||||
//Uint8 bXInputHaptic; // Supports force feedback via XInput.
|
||||
DWORD userIndex; // The XInput device index, in the range [0, XUSER_MAX_COUNT-1] (probably [0,3]).
|
||||
XINPUT_STATE XInputState; // the last-read in XInputState, kept around to compare old and new values
|
||||
SDL_bool isDeviceConnected; // was the device connected (on the last detection-polling, or during backend-initialization)?
|
||||
SDL_bool isDeviceConnectionEventPending; // was a device added, and is the associated add-event pending?
|
||||
SDL_bool isDeviceRemovalEventPending; // was the device removed, and is the associated remove-event pending?
|
||||
};
|
||||
|
||||
/* Keep track of data on all XInput devices, regardless of whether or not
|
||||
they've been opened (via SDL_JoystickOpen).
|
||||
*/
|
||||
static struct joystick_hwdata g_XInputData[XUSER_MAX_COUNT];
|
||||
|
||||
/* Device detection can be extremely costly performance-wise, in some cases.
|
||||
In particular, if no devices are connected, calls to detect a single device,
|
||||
via either XInputGetState() or XInputGetCapabilities(), can take upwards of
|
||||
20 ms on a 1st generation Surface RT, more if devices are detected across
|
||||
all of of XInput's four device slots. WinRT and XInput do not appear to
|
||||
have callback-based APIs to notify an app when a device is connected, at
|
||||
least as of Windows 8.1. The synchronous XInput calls must be used.
|
||||
|
||||
Once a device is connected, calling XInputGetState() is a much less costly
|
||||
operation, with individual calls costing well under 1 ms, and often under
|
||||
0.1 ms [on a 1st gen Surface RT].
|
||||
|
||||
With XInput's performance limitations in mind, a separate device-detection
|
||||
thread will be utilized (by SDL) to try to move costly XInput calls off the
|
||||
main thread. Polling of active devices still, however, occurs on the main
|
||||
thread.
|
||||
*/
|
||||
static SDL_Thread * g_DeviceDetectionThread = NULL;
|
||||
static SDL_mutex * g_DeviceInfoLock = NULL;
|
||||
static SDL_bool g_DeviceDetectionQuit = SDL_FALSE;
|
||||
|
||||
/* Main function for the device-detection thread.
|
||||
*/
|
||||
static int
|
||||
DeviceDetectionThreadMain(void * _data)
|
||||
{
|
||||
DWORD result;
|
||||
XINPUT_CAPABILITIES tempXInputCaps;
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
/* See if the device-detection thread is being asked to shutdown.
|
||||
*/
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
if (g_DeviceDetectionQuit) {
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
break;
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
|
||||
/* Add a short delay to prevent the device-detection thread from eating
|
||||
up too much CPU time:
|
||||
*/
|
||||
SDL_Delay(300);
|
||||
|
||||
/* TODO, WinRT: try making the device-detection thread wakeup sooner from its CPU-preserving SDL_Delay, if the thread was asked to quit.
|
||||
*/
|
||||
|
||||
/* See if any new devices are connected. */
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
if (!g_XInputData[i].isDeviceConnected &&
|
||||
!g_XInputData[i].isDeviceConnectionEventPending &&
|
||||
!g_XInputData[i].isDeviceRemovalEventPending)
|
||||
{
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
result = XInputGetCapabilities(i, 0, &tempXInputCaps);
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
/* Yes, a device is connected. Mark it as such.
|
||||
Others will be told about this (via an
|
||||
SDL_JOYDEVICEADDED event) in the next call to
|
||||
SDL_SYS_JoystickDetect.
|
||||
*/
|
||||
g_XInputData[i].isDeviceConnected = SDL_TRUE;
|
||||
g_XInputData[i].isDeviceConnectionEventPending = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
XINPUT_STATE tempXInputState;
|
||||
int i;
|
||||
|
||||
SDL_zero(g_XInputData);
|
||||
|
||||
/* Make initial notes on whether or not devices are connected (or not).
|
||||
*/
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
result = XInputGetState(i, &tempXInputState);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
g_XInputData[i].isDeviceConnected = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start up the device-detection thread.
|
||||
*/
|
||||
g_DeviceDetectionQuit = SDL_FALSE;
|
||||
g_DeviceInfoLock = SDL_CreateMutex();
|
||||
g_DeviceDetectionThread = SDL_CreateThread(DeviceDetectionThreadMain, "SDL_joystick", NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
int joystickCount = 0;
|
||||
DWORD i;
|
||||
|
||||
/* Iterate through each possible XInput device and see if something
|
||||
was connected (at joystick init, or during the last polling).
|
||||
*/
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
if (g_XInputData[i].isDeviceConnected) {
|
||||
++joystickCount;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
|
||||
return joystickCount;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
DWORD i;
|
||||
SDL_Event event;
|
||||
|
||||
/* Iterate through each possible XInput device, seeing if any devices
|
||||
have been connected, or if they were removed.
|
||||
*/
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
/* See if any new devices are connected. */
|
||||
if (g_XInputData[i].isDeviceConnectionEventPending) {
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = i;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g_XInputData[i].isDeviceConnectionEventPending = SDL_FALSE;
|
||||
} else if (g_XInputData[i].isDeviceRemovalEventPending) {
|
||||
/* A device was previously marked as removed (by
|
||||
SDL_SYS_JoystickUpdate). Tell others about the device removal.
|
||||
*/
|
||||
|
||||
g_XInputData[i].isDeviceRemovalEventPending = SDL_FALSE;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = i; //joystick->hwdata->userIndex;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
/* Since XInput, or WinRT, provides any events to indicate when a game
|
||||
controller gets connected, and instead indicates device availability
|
||||
solely through polling, we'll poll (for new devices).
|
||||
*/
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Internal function to retreive device capabilities.
|
||||
This function will return an SDL-standard value of 0 on success
|
||||
(a device is connected, and data on it was retrieved), or -1
|
||||
on failure (no device was connected, or some other error
|
||||
occurred. SDL_SetError() will be invoked to set an appropriate
|
||||
error message.
|
||||
*/
|
||||
static int
|
||||
SDL_XInput_GetDeviceCapabilities(int device_index, XINPUT_CAPABILITIES * pDeviceCaps)
|
||||
{
|
||||
HRESULT dwResult;
|
||||
|
||||
/* Make sure that the device index is a valid one. If not, return to the
|
||||
caller with an error.
|
||||
*/
|
||||
if (device_index < 0 || device_index >= XUSER_MAX_COUNT) {
|
||||
return SDL_SetError("invalid/unavailable device index");
|
||||
}
|
||||
|
||||
/* See if a device exists, and if so, what its capabilities are. If a
|
||||
device is not available, return to the caller with an error.
|
||||
*/
|
||||
switch ((dwResult = XInputGetCapabilities(device_index, 0, pDeviceCaps))) {
|
||||
case ERROR_SUCCESS:
|
||||
/* A device is available, and its capabilities were retrieved! */
|
||||
return 0;
|
||||
case ERROR_DEVICE_NOT_CONNECTED:
|
||||
return SDL_SetError("no device is connected at joystick index, %d", device_index);
|
||||
default:
|
||||
return SDL_SetError("an unknown error occurred when retrieving info on a device at joystick index, %d", device_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
XINPUT_CAPABILITIES deviceCaps;
|
||||
|
||||
if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
|
||||
/* Uh oh. Device capabilities couldn't be retrieved. Return to the
|
||||
caller. SDL_SetError() has already been invoked (with relevant
|
||||
information).
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (deviceCaps.SubType) {
|
||||
default:
|
||||
if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return "Undefined game controller";
|
||||
} else {
|
||||
return "Undefined controller";
|
||||
}
|
||||
case XINPUT_DEVSUBTYPE_UNKNOWN:
|
||||
if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return "Unknown game controller";
|
||||
} else {
|
||||
return "Unknown controller";
|
||||
}
|
||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||
return "Gamepad controller";
|
||||
case XINPUT_DEVSUBTYPE_WHEEL:
|
||||
return "Racing wheel controller";
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
||||
return "Arcade stick controller";
|
||||
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
||||
return "Flight stick controller";
|
||||
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
||||
return "Dance pad controller";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR:
|
||||
return "Guitar controller";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
|
||||
return "Guitar controller, Alternate";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_BASS:
|
||||
return "Guitar controller, Bass";
|
||||
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
||||
return "Drum controller";
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_PAD:
|
||||
return "Arcade pad controller";
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
XINPUT_CAPABILITIES deviceCaps;
|
||||
|
||||
if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
|
||||
/* Uh oh. Device capabilities couldn't be retrieved. Return to the
|
||||
caller. SDL_SetError() has already been invoked (with relevant
|
||||
information).
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* For now, only game pads are supported. If the device is something other
|
||||
than that, return an error to the caller.
|
||||
*/
|
||||
if (deviceCaps.Type != XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return SDL_SetError("a device is connected (at joystick index, %d), but it is of an unknown device type (deviceCaps.Flags=%ul)",
|
||||
device_index, (unsigned int)deviceCaps.Flags);
|
||||
}
|
||||
|
||||
/* Create the joystick data structure */
|
||||
joystick->instance_id = device_index;
|
||||
joystick->hwdata = &g_XInputData[device_index];
|
||||
|
||||
// The XInput API has a hard coded button/axis mapping, so we just match it
|
||||
joystick->naxes = 6;
|
||||
joystick->nbuttons = 15;
|
||||
joystick->nballs = 0;
|
||||
joystick->nhats = 0;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
SDL_bool isDeviceConnected;
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
isDeviceConnected = joystick->hwdata->isDeviceConnected;
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
return isDeviceConnected;
|
||||
}
|
||||
|
||||
/* Function to return > 0 if a bit array of buttons differs after applying a mask
|
||||
*/
|
||||
static int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
|
||||
{
|
||||
return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
HRESULT result;
|
||||
XINPUT_STATE prevXInputState;
|
||||
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
|
||||
/* Before polling for new data, make note of the old data */
|
||||
prevXInputState = joystick->hwdata->XInputState;
|
||||
|
||||
/* Poll for new data */
|
||||
result = XInputGetState(joystick->hwdata->userIndex, &joystick->hwdata->XInputState);
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED) {
|
||||
if (joystick->hwdata->isDeviceConnected) {
|
||||
joystick->hwdata->isDeviceConnected = SDL_FALSE;
|
||||
joystick->hwdata->isDeviceRemovalEventPending = SDL_TRUE;
|
||||
/* TODO, WinRT: make sure isDeviceRemovalEventPending gets cleared as appropriate, and that quick re-plugs don't cause trouble */
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure the device is marked as connected */
|
||||
joystick->hwdata->isDeviceConnected = SDL_TRUE;
|
||||
|
||||
// only fire events if the data changed from last time
|
||||
if ( joystick->hwdata->XInputState.dwPacketNumber != 0
|
||||
&& joystick->hwdata->XInputState.dwPacketNumber != prevXInputState.dwPacketNumber )
|
||||
{
|
||||
XINPUT_STATE *pXInputState = &joystick->hwdata->XInputState;
|
||||
XINPUT_STATE *pXInputStatePrev = &prevXInputState;
|
||||
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX );
|
||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-1*pXInputState->Gamepad.sThumbLY-1) );
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX );
|
||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-1*pXInputState->Gamepad.sThumbRY-1) );
|
||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)((int)pXInputState->Gamepad.bLeftTrigger*32767/255) );
|
||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)((int)pXInputState->Gamepad.bRightTrigger*32767/255) );
|
||||
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) )
|
||||
SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) )
|
||||
SDL_PrivateJoystickButton(joystick, 1, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_LEFT ) )
|
||||
SDL_PrivateJoystickButton(joystick, 2, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_RIGHT ) )
|
||||
SDL_PrivateJoystickButton(joystick, 3, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_START ) )
|
||||
SDL_PrivateJoystickButton(joystick, 4, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_START ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_BACK ) )
|
||||
SDL_PrivateJoystickButton(joystick, 5, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_THUMB ) )
|
||||
SDL_PrivateJoystickButton(joystick, 6, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_THUMB ) )
|
||||
SDL_PrivateJoystickButton(joystick, 7, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_SHOULDER ) )
|
||||
SDL_PrivateJoystickButton(joystick, 8, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER ) )
|
||||
SDL_PrivateJoystickButton(joystick, 9, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_A ) )
|
||||
SDL_PrivateJoystickButton(joystick, 10, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_A ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_B ) )
|
||||
SDL_PrivateJoystickButton(joystick, 11, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_B ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_X ) )
|
||||
SDL_PrivateJoystickButton(joystick, 12, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_X ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_Y ) )
|
||||
SDL_PrivateJoystickButton(joystick, 13, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_Y ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, 0x400 ) )
|
||||
SDL_PrivateJoystickButton(joystick, 14, pXInputState->Gamepad.wButtons & 0x400 ? SDL_PRESSED : SDL_RELEASED ); // 0x400 is the undocumented code for the guide button
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
/* Clear cached button data on the joystick */
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
SDL_zero(joystick->hwdata->XInputState);
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
|
||||
/* There's need to free 'hwdata', as it's a pointer to a global array.
|
||||
The field will be cleared anyways, just to indicate that it's not
|
||||
currently needed.
|
||||
*/
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
/* Tell the joystick detection thread to stop, then wait for it to finish */
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
g_DeviceDetectionQuit = SDL_TRUE;
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
SDL_WaitThread(g_DeviceDetectionThread, NULL);
|
||||
|
||||
/* Clean up device-detection stuff */
|
||||
SDL_DestroyMutex(g_DeviceInfoLock);
|
||||
g_DeviceInfoLock = NULL;
|
||||
g_DeviceDetectionThread = NULL;
|
||||
g_DeviceDetectionQuit = SDL_FALSE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_IsXInputDeviceIndex(int device_index)
|
||||
{
|
||||
/* The XInput-capable DirectInput joystick backend implements the same
|
||||
function (SDL_SYS_IsXInputDeviceIndex), however in that case, not all
|
||||
joystick devices are XInput devices. In this case, with the
|
||||
WinRT-enabled XInput-only backend, all "joystick" devices are XInput
|
||||
devices.
|
||||
*/
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_XINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user