mirror of https://github.com/encounter/SDL.git
Added a Windows Gaming Input joystick driver
This driver supports the Razer Atrox Arcade Stick Some of the quirks of this driver, inherent in Windows Gaming Input: * There will never appear to be controllers connected at startup. You must support hot-plugging in order to see these controllers. * You can't read the state of the guide button * You can't get controller events in the background
This commit is contained in:
parent
b90b59279e
commit
aba2792896
|
@ -418,11 +418,13 @@
|
||||||
<ClCompile Include="..\..\src\events\SDL_windowevents.c" />
|
<ClCompile Include="..\..\src\events\SDL_windowevents.c" />
|
||||||
<ClCompile Include="..\..\src\file\SDL_rwops.c" />
|
<ClCompile Include="..\..\src\file\SDL_rwops.c" />
|
||||||
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
|
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
|
||||||
|
<ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
|
||||||
<ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
|
<ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
|
||||||
<ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
|
<ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
|
||||||
<ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
|
<ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
|
||||||
<ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
|
<ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
|
||||||
<ClCompile Include="..\..\src\hidapi\windows\hid.c" />
|
<ClCompile Include="..\..\src\hidapi\windows\hid.c" />
|
||||||
|
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
||||||
|
@ -438,6 +440,7 @@
|
||||||
<ClCompile Include="..\..\src\joystick\windows\SDL_mmjoystick.c" />
|
<ClCompile Include="..\..\src\joystick\windows\SDL_mmjoystick.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />
|
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
|
<ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
|
||||||
|
<ClCompile Include="..\..\src\joystick\windows\SDL_windows_gaming_input.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
|
<ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
|
||||||
<ClCompile Include="..\..\src\libm\e_atan2.c" />
|
<ClCompile Include="..\..\src\libm\e_atan2.c" />
|
||||||
<ClCompile Include="..\..\src\libm\e_exp.c" />
|
<ClCompile Include="..\..\src\libm\e_exp.c" />
|
||||||
|
|
|
@ -484,6 +484,9 @@
|
||||||
<ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb.c" />
|
<ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />
|
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />
|
||||||
<ClCompile Include="..\..\src\sensor\windows\SDL_windowssensor.c" />
|
<ClCompile Include="..\..\src\sensor\windows\SDL_windowssensor.c" />
|
||||||
|
<ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
|
||||||
|
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
|
||||||
|
<ClCompile Include="..\..\src\joystick\windows\SDL_windows_gaming_input.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\..\src\main\windows\version.rc" />
|
<ResourceCompile Include="..\..\src\main\windows\version.rc" />
|
||||||
|
|
|
@ -198,6 +198,7 @@ typedef unsigned int uintptr_t;
|
||||||
#define SDL_JOYSTICK_HIDAPI 1
|
#define SDL_JOYSTICK_HIDAPI 1
|
||||||
#define SDL_JOYSTICK_RAWINPUT 1
|
#define SDL_JOYSTICK_RAWINPUT 1
|
||||||
#define SDL_JOYSTICK_VIRTUAL 1
|
#define SDL_JOYSTICK_VIRTUAL 1
|
||||||
|
/*#define SDL_JOYSTICK_WGI 1*/
|
||||||
#define SDL_JOYSTICK_XINPUT 1
|
#define SDL_JOYSTICK_XINPUT 1
|
||||||
#define SDL_HAPTIC_DINPUT 1
|
#define SDL_HAPTIC_DINPUT 1
|
||||||
#define SDL_HAPTIC_XINPUT 1
|
#define SDL_HAPTIC_XINPUT 1
|
||||||
|
@ -260,3 +261,5 @@ typedef unsigned int uintptr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* SDL_config_windows_h_ */
|
#endif /* SDL_config_windows_h_ */
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -1045,7 +1045,7 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForNameAndGUID(const
|
||||||
}
|
}
|
||||||
#endif /* __LINUX__ */
|
#endif /* __LINUX__ */
|
||||||
|
|
||||||
if (!mapping && name) {
|
if (!mapping && name && !SDL_IsJoystickWGI(guid)) {
|
||||||
if (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box") || SDL_strstr(name, "XBOX")) {
|
if (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box") || SDL_strstr(name, "XBOX")) {
|
||||||
mapping = s_pXInputMapping;
|
mapping = s_pXInputMapping;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ static const char *s_ControllerMappings [] =
|
||||||
#if SDL_JOYSTICK_XINPUT
|
#if SDL_JOYSTICK_XINPUT
|
||||||
"xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
"xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||||
#endif
|
#endif
|
||||||
|
#if SDL_JOYSTICK_WGI
|
||||||
|
"0300000032150000000a000000007703,Razer Atrox Arcade Stick,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,dpup:b10,dpdown:b12,dpleft:b13,dpright:b11,lefttrigger:b8,righttrigger:b9,",
|
||||||
|
#endif
|
||||||
#if SDL_JOYSTICK_DINPUT
|
#if SDL_JOYSTICK_DINPUT
|
||||||
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,",
|
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,",
|
||||||
"03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,",
|
"03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,",
|
||||||
|
|
|
@ -58,6 +58,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
|
||||||
#ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
|
#ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
|
||||||
&SDL_HIDAPI_JoystickDriver,
|
&SDL_HIDAPI_JoystickDriver,
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(SDL_JOYSTICK_WGI)
|
||||||
|
&SDL_WGI_JoystickDriver,
|
||||||
|
#endif
|
||||||
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
|
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
|
||||||
&SDL_WINDOWS_JoystickDriver,
|
&SDL_WINDOWS_JoystickDriver,
|
||||||
#endif
|
#endif
|
||||||
|
@ -1731,6 +1734,12 @@ SDL_IsJoystickXInput(SDL_JoystickGUID guid)
|
||||||
return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE;
|
return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
SDL_IsJoystickWGI(SDL_JoystickGUID guid)
|
||||||
|
{
|
||||||
|
return (guid.data[14] == 'w') ? SDL_TRUE : SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_bool
|
SDL_bool
|
||||||
SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
|
SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
|
||||||
{
|
{
|
||||||
|
@ -1840,6 +1849,10 @@ static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SDL_IsJoystickWGI(guid)) {
|
||||||
|
return (SDL_JoystickType)guid.data[15];
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_IsJoystickVirtual(guid)) {
|
if (SDL_IsJoystickVirtual(guid)) {
|
||||||
return (SDL_JoystickType)guid.data[15];
|
return (SDL_JoystickType)guid.data[15];
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,9 @@ extern SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_i
|
||||||
/* Function to return whether a joystick guid comes from the XInput driver */
|
/* Function to return whether a joystick guid comes from the XInput driver */
|
||||||
extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid);
|
extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid);
|
||||||
|
|
||||||
|
/* Function to return whether a joystick guid comes from the WGI driver */
|
||||||
|
extern SDL_bool SDL_IsJoystickWGI(SDL_JoystickGUID guid);
|
||||||
|
|
||||||
/* Function to return whether a joystick guid comes from the HIDAPI driver */
|
/* Function to return whether a joystick guid comes from the HIDAPI driver */
|
||||||
extern SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid);
|
extern SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid);
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@ extern SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver;
|
||||||
extern SDL_JoystickDriver SDL_IOS_JoystickDriver;
|
extern SDL_JoystickDriver SDL_IOS_JoystickDriver;
|
||||||
extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
|
extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
|
||||||
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;
|
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;
|
||||||
|
extern SDL_JoystickDriver SDL_WGI_JoystickDriver;
|
||||||
extern SDL_JoystickDriver SDL_WINDOWS_JoystickDriver;
|
extern SDL_JoystickDriver SDL_WINDOWS_JoystickDriver;
|
||||||
|
|
||||||
#endif /* SDL_sysjoystick_h_ */
|
#endif /* SDL_sysjoystick_h_ */
|
||||||
|
|
|
@ -0,0 +1,705 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2020 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_WGI
|
||||||
|
|
||||||
|
#include "SDL_endian.h"
|
||||||
|
#include "SDL_events.h"
|
||||||
|
#include "../SDL_sysjoystick.h"
|
||||||
|
|
||||||
|
#include "../../core/windows/SDL_windows.h"
|
||||||
|
#define COBJMACROS
|
||||||
|
#include "windows.gaming.input.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct joystick_hwdata
|
||||||
|
{
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo *battery;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad;
|
||||||
|
UINT64 timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct WindowsGamingInputControllerState {
|
||||||
|
SDL_JoystickID instance_id;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller;
|
||||||
|
char *name;
|
||||||
|
SDL_JoystickGUID guid;
|
||||||
|
SDL_JoystickType type;
|
||||||
|
int naxes;
|
||||||
|
int nhats;
|
||||||
|
int nbuttons;
|
||||||
|
} WindowsGamingInputControllerState;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics *statics;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics *arcade_stick_statics;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2 *arcade_stick_statics2;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics *flight_stick_statics;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics *gamepad_statics;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2 *gamepad_statics2;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics *racing_wheel_statics;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2 *racing_wheel_statics2;
|
||||||
|
EventRegistrationToken controller_added_token;
|
||||||
|
EventRegistrationToken controller_removed_token;
|
||||||
|
int controller_count;
|
||||||
|
WindowsGamingInputControllerState *controllers;
|
||||||
|
} wgi;
|
||||||
|
|
||||||
|
static const IID IID_IRawGameControllerStatics = { 0xEB8D0792, 0xE95A, 0x4B19, { 0xAF, 0xC7, 0x0A, 0x59, 0xF8, 0xBF, 0x75, 0x9E } };
|
||||||
|
static const IID IID_IRawGameController = { 0x7CAD6D91, 0xA7E1, 0x4F71, { 0x9A, 0x78, 0x33, 0xE9, 0xC5, 0xDF, 0xEA, 0x62 } };
|
||||||
|
static const IID IID_IRawGameController2 = { 0x43C0C035, 0xBB73, 0x4756, { 0xA7, 0x87, 0x3E, 0xD6, 0xBE, 0xA6, 0x17, 0xBD } };
|
||||||
|
static const IID IID_IEventHandler_RawGameController = { 0x00621c22, 0x42e8, 0x529f, { 0x92, 0x70, 0x83, 0x6b, 0x32, 0x93, 0x1d, 0x72 } };
|
||||||
|
static const IID IID_IGameController = { 0x1BAF6522, 0x5F64, 0x42C5, { 0x82, 0x67, 0xB9, 0xFE, 0x22, 0x15, 0xBF, 0xBD } };
|
||||||
|
static const IID IID_IGameControllerBatteryInfo = { 0xDCECC681, 0x3963, 0x4DA6, { 0x95, 0x5D, 0x55, 0x3F, 0x3B, 0x6F, 0x61, 0x61 } };
|
||||||
|
static const IID IID_IArcadeStickStatics = { 0x5C37B8C8, 0x37B1, 0x4AD8, { 0x94, 0x58, 0x20, 0x0F, 0x1A, 0x30, 0x01, 0x8E } };
|
||||||
|
static const IID IID_IArcadeStickStatics2 = { 0x52B5D744, 0xBB86, 0x445A, { 0xB5, 0x9C, 0x59, 0x6F, 0x0E, 0x2A, 0x49, 0xDF } };
|
||||||
|
static const IID IID_IArcadeStick = { 0xB14A539D, 0xBEFB, 0x4C81, { 0x80, 0x51, 0x15, 0xEC, 0xF3, 0xB1, 0x30, 0x36 } };
|
||||||
|
static const IID IID_IFlightStickStatics = { 0x5514924A, 0xFECC, 0x435E, { 0x83, 0xDC, 0x5C, 0xEC, 0x8A, 0x18, 0xA5, 0x20 } };
|
||||||
|
static const IID IID_IFlightStick = { 0xB4A2C01C, 0xB83B, 0x4459, { 0xA1, 0xA9, 0x97, 0xB0, 0x3C, 0x33, 0xDA, 0x7C } };
|
||||||
|
static const IID IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
|
||||||
|
static const IID IID_IGamepadStatics2 = { 0x42676DC5, 0x0856, 0x47C4, { 0x92, 0x13, 0xB3, 0x95, 0x50, 0x4C, 0x3A, 0x3C } };
|
||||||
|
static const IID IID_IGamepad = { 0xBC7BB43C, 0x0A69, 0x3903, { 0x9E, 0x9D, 0xA5, 0x0F, 0x86, 0xA4, 0x5D, 0xE5 } };
|
||||||
|
static const IID IID_IRacingWheelStatics = { 0x3AC12CD5, 0x581B, 0x4936, { 0x9F, 0x94, 0x69, 0xF1, 0xE6, 0x51, 0x4C, 0x7D } };
|
||||||
|
static const IID IID_IRacingWheelStatics2 = { 0xE666BCAA, 0xEDFD, 0x4323, { 0xA9, 0xF6, 0x3C, 0x38, 0x40, 0x48, 0xD1, 0xED } };
|
||||||
|
static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };
|
||||||
|
|
||||||
|
extern SDL_bool SDL_XINPUT_Enabled(void);
|
||||||
|
|
||||||
|
static SDL_bool
|
||||||
|
SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
|
||||||
|
{
|
||||||
|
PRAWINPUTDEVICELIST raw_devices = NULL;
|
||||||
|
UINT i, raw_device_count = 0;
|
||||||
|
LONG vidpid = MAKELONG(vendor, product);
|
||||||
|
|
||||||
|
if (!SDL_XINPUT_Enabled()) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go through RAWINPUT (WinXP and later) to find HID devices. */
|
||||||
|
if ((GetRawInputDeviceList(NULL, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!raw_device_count)) {
|
||||||
|
return SDL_FALSE; /* oh well. */
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * raw_device_count);
|
||||||
|
if (raw_devices == NULL) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetRawInputDeviceList(raw_devices, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
|
||||||
|
SDL_free(raw_devices);
|
||||||
|
raw_devices = NULL;
|
||||||
|
return SDL_FALSE; /* oh well. */
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < raw_device_count; i++) {
|
||||||
|
RID_DEVICE_INFO rdi;
|
||||||
|
char devName[128];
|
||||||
|
UINT rdiSize = sizeof(rdi);
|
||||||
|
UINT nameSize = SDL_arraysize(devName);
|
||||||
|
|
||||||
|
rdi.cbSize = sizeof(rdi);
|
||||||
|
if ((raw_devices[i].dwType == RIM_TYPEHID) &&
|
||||||
|
(GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
|
||||||
|
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == vidpid) &&
|
||||||
|
(GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
|
||||||
|
(SDL_strstr(devName, "IG_") != NULL)) {
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, REFIID riid, void **ppvObject)
|
||||||
|
{
|
||||||
|
if (!ppvObject) {
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppvObject = NULL;
|
||||||
|
if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IEventHandler_RawGameController)) {
|
||||||
|
*ppvObject = This;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_AddRef(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_Release(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController * *e)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller = NULL;
|
||||||
|
|
||||||
|
hr = IUnknown_QueryInterface((IUnknown *)e, &IID_IRawGameController, (void **)&controller);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
char *name = NULL;
|
||||||
|
SDL_JoystickGUID guid;
|
||||||
|
Uint16 vendor = 0;
|
||||||
|
Uint16 product = 0;
|
||||||
|
Uint16 version = 0;
|
||||||
|
SDL_JoystickType type = SDL_JOYSTICK_TYPE_UNKNOWN;
|
||||||
|
Uint16 *guid16 = (Uint16 *)guid.data;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller = NULL;
|
||||||
|
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareVendorId(controller, &vendor);
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareProductId(controller, &product);
|
||||||
|
|
||||||
|
if (SDL_IsXInputDevice(vendor, product)) {
|
||||||
|
/* This will be handled by the XInput driver */
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
HSTRING hString;
|
||||||
|
|
||||||
|
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
HMODULE hModule = LoadLibraryA("combase.dll");
|
||||||
|
if (hModule != NULL) {
|
||||||
|
typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length);
|
||||||
|
|
||||||
|
WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer");
|
||||||
|
if (WindowsGetStringRawBufferFunc) {
|
||||||
|
PCWSTR string = WindowsGetStringRawBufferFunc(hString, NULL);
|
||||||
|
if (string) {
|
||||||
|
name = WIN_StringToUTF8(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeLibrary(hModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IGameController, (void **)&gamecontroller))) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIArcadeStick *arcade_stick = NULL;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIFlightStick *flight_stick = NULL;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad = NULL;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRacingWheel *racing_wheel = NULL;
|
||||||
|
|
||||||
|
if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, gamecontroller, &gamepad)) && gamepad) {
|
||||||
|
type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(gamepad);
|
||||||
|
} else if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, gamecontroller, &arcade_stick)) && arcade_stick) {
|
||||||
|
type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIArcadeStick_Release(arcade_stick);
|
||||||
|
} else if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, gamecontroller, &flight_stick)) && flight_stick) {
|
||||||
|
type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIFlightStick_Release(flight_stick);
|
||||||
|
} else if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, gamecontroller, &racing_wheel)) && racing_wheel) {
|
||||||
|
type = SDL_JOYSTICK_TYPE_WHEEL;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRacingWheel_Release(racing_wheel);
|
||||||
|
}
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Is there any way to tell whether this is a Bluetooth device? */
|
||||||
|
*guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
|
||||||
|
*guid16++ = 0;
|
||||||
|
*guid16++ = SDL_SwapLE16(vendor);
|
||||||
|
*guid16++ = 0;
|
||||||
|
*guid16++ = SDL_SwapLE16(product);
|
||||||
|
*guid16++ = 0;
|
||||||
|
*guid16++ = SDL_SwapLE16(version);
|
||||||
|
*guid16++ = 0;
|
||||||
|
|
||||||
|
/* Note that this is a Windows Gaming Input device for special handling elsewhere */
|
||||||
|
guid.data[14] = 'w';
|
||||||
|
guid.data[15] = (Uint8)type;
|
||||||
|
|
||||||
|
if (SDL_ShouldIgnoreJoystick(name, guid)) {
|
||||||
|
SDL_free(name);
|
||||||
|
} else {
|
||||||
|
/* New device, add it */
|
||||||
|
WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1));
|
||||||
|
if (controllers) {
|
||||||
|
WindowsGamingInputControllerState *state = &controllers[wgi.controller_count];
|
||||||
|
SDL_JoystickID joystickID = SDL_GetNextJoystickInstanceID();
|
||||||
|
|
||||||
|
SDL_zerop(state);
|
||||||
|
state->instance_id = joystickID;
|
||||||
|
state->controller = controller;
|
||||||
|
state->name = name;
|
||||||
|
state->guid = guid;
|
||||||
|
state->type = type;
|
||||||
|
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(controller, &state->nbuttons);
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(controller, &state->naxes);
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_SwitchCount(controller, &state->nhats);
|
||||||
|
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(controller);
|
||||||
|
|
||||||
|
++wgi.controller_count;
|
||||||
|
wgi.controllers = controllers;
|
||||||
|
|
||||||
|
SDL_PrivateJoystickAdded(joystickID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeRemoved(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController * This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController * *e)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller = NULL;
|
||||||
|
|
||||||
|
hr = IUnknown_QueryInterface((IUnknown *)e, &IID_IRawGameController, (void **)&controller);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < wgi.controller_count ; i++) {
|
||||||
|
if (wgi.controllers[i].controller == controller) {
|
||||||
|
WindowsGamingInputControllerState *state = &wgi.controllers[i];
|
||||||
|
SDL_JoystickID joystickID = state->instance_id;
|
||||||
|
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(state->controller);
|
||||||
|
|
||||||
|
SDL_free(state->name);
|
||||||
|
|
||||||
|
--wgi.controller_count;
|
||||||
|
if (i < wgi.controller_count) {
|
||||||
|
SDL_memmove(&wgi.controllers[i], &wgi.controllers[i + 1], (wgi.controller_count - i) * sizeof(wgi.controllers[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_PrivateJoystickRemoved(joystickID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl controller_added_vtbl = {
|
||||||
|
IEventHandler_CRawGameControllerVtbl_QueryInterface,
|
||||||
|
IEventHandler_CRawGameControllerVtbl_AddRef,
|
||||||
|
IEventHandler_CRawGameControllerVtbl_Release,
|
||||||
|
IEventHandler_CRawGameControllerVtbl_InvokeAdded
|
||||||
|
};
|
||||||
|
static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController controller_added = {
|
||||||
|
&controller_added_vtbl
|
||||||
|
};
|
||||||
|
|
||||||
|
static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl controller_removed_vtbl = {
|
||||||
|
IEventHandler_CRawGameControllerVtbl_QueryInterface,
|
||||||
|
IEventHandler_CRawGameControllerVtbl_AddRef,
|
||||||
|
IEventHandler_CRawGameControllerVtbl_Release,
|
||||||
|
IEventHandler_CRawGameControllerVtbl_InvokeRemoved
|
||||||
|
};
|
||||||
|
static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController controller_removed = {
|
||||||
|
&controller_removed_vtbl
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
WGI_JoystickInit(void)
|
||||||
|
{
|
||||||
|
if (FAILED(WIN_CoInitialize())) {
|
||||||
|
return SDL_SetError("CoInitialize() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
HMODULE hModule = LoadLibraryA("combase.dll");
|
||||||
|
if (hModule != NULL) {
|
||||||
|
typedef HRESULT (WINAPI *WindowsCreateString_t)(PCNZWCH sourceString, UINT32 length, HSTRING* string);
|
||||||
|
typedef HRESULT (WINAPI *WindowsDeleteString_t)(HSTRING string);
|
||||||
|
typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
|
||||||
|
|
||||||
|
WindowsCreateString_t WindowsCreateStringFunc = (WindowsCreateString_t)GetProcAddress(hModule, "WindowsCreateString");
|
||||||
|
WindowsDeleteString_t WindowsDeleteStringFunc = (WindowsDeleteString_t)GetProcAddress(hModule, "WindowsDeleteString");
|
||||||
|
RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
|
||||||
|
if (WindowsCreateStringFunc && WindowsDeleteStringFunc && RoGetActivationFactoryFunc) {
|
||||||
|
LPTSTR pNamespace;
|
||||||
|
HSTRING hNamespaceString;
|
||||||
|
|
||||||
|
pNamespace = L"Windows.Gaming.Input.RawGameController";
|
||||||
|
hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRawGameControllerStatics, &wgi.statics);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%x", hr);
|
||||||
|
}
|
||||||
|
WindowsDeleteStringFunc(hNamespaceString);
|
||||||
|
}
|
||||||
|
|
||||||
|
pNamespace = L"Windows.Gaming.Input.ArcadeStick";
|
||||||
|
hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IArcadeStickStatics, &wgi.arcade_stick_statics);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID_IArcadeStickStatics2, &wgi.arcade_stick_statics2);
|
||||||
|
} else {
|
||||||
|
SDL_SetError("Couldn't find IID_IArcadeStickStatics: 0x%x", hr);
|
||||||
|
}
|
||||||
|
WindowsDeleteStringFunc(hNamespaceString);
|
||||||
|
}
|
||||||
|
|
||||||
|
pNamespace = L"Windows.Gaming.Input.FlightStick";
|
||||||
|
hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IFlightStickStatics, &wgi.flight_stick_statics);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%x", hr);
|
||||||
|
}
|
||||||
|
WindowsDeleteStringFunc(hNamespaceString);
|
||||||
|
}
|
||||||
|
|
||||||
|
pNamespace = L"Windows.Gaming.Input.Gamepad";
|
||||||
|
hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, &wgi.gamepad_statics);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, &wgi.gamepad_statics2);
|
||||||
|
} else {
|
||||||
|
SDL_SetError("Couldn't find IGamepadStatics: 0x%x", hr);
|
||||||
|
}
|
||||||
|
WindowsDeleteStringFunc(hNamespaceString);
|
||||||
|
}
|
||||||
|
|
||||||
|
pNamespace = L"Windows.Gaming.Input.RacingWheel";
|
||||||
|
hr = WindowsCreateStringFunc(pNamespace, SDL_wcslen(pNamespace), &hNamespaceString);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, &wgi.racing_wheel_statics);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID_IRacingWheelStatics2, &wgi.racing_wheel_statics2);
|
||||||
|
} else {
|
||||||
|
SDL_SetError("Couldn't find IRacingWheelStatics: 0x%x", hr);
|
||||||
|
}
|
||||||
|
WindowsDeleteStringFunc(hNamespaceString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeLibrary(hModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wgi.statics) {
|
||||||
|
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerAdded(wgi.statics, &controller_added, &wgi.controller_added_token);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
SDL_SetError("add_RawGameControllerAdded() failed: 0x%x\n", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerRemoved(wgi.statics, &controller_removed, &wgi.controller_removed_token);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
SDL_SetError("add_RawGameControllerRemoved() failed: 0x%x\n", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
WGI_JoystickGetCount(void)
|
||||||
|
{
|
||||||
|
return wgi.controller_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WGI_JoystickDetect(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
WGI_JoystickGetDeviceName(int device_index)
|
||||||
|
{
|
||||||
|
return wgi.controllers[device_index].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
WGI_JoystickGetDevicePlayerIndex(int device_index)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WGI_JoystickSetDevicePlayerIndex(int device_index, int player_index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_JoystickGUID
|
||||||
|
WGI_JoystickGetDeviceGUID(int device_index)
|
||||||
|
{
|
||||||
|
return wgi.controllers[device_index].guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_JoystickID
|
||||||
|
WGI_JoystickGetDeviceInstanceID(int device_index)
|
||||||
|
{
|
||||||
|
return wgi.controllers[device_index].instance_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
WGI_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||||
|
{
|
||||||
|
WindowsGamingInputControllerState *state = &wgi.controllers[device_index];
|
||||||
|
struct joystick_hwdata *hwdata;
|
||||||
|
boolean wireless = SDL_FALSE;
|
||||||
|
|
||||||
|
hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
|
||||||
|
if (!hwdata) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
joystick->hwdata = hwdata;
|
||||||
|
|
||||||
|
hwdata->controller = state->controller;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(hwdata->controller);
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameController, (void **)&hwdata->gamecontroller);
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameControllerBatteryInfo, (void **)&hwdata->battery);
|
||||||
|
|
||||||
|
if (wgi.gamepad_statics2) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, hwdata->gamecontroller, &hwdata->gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hwdata->gamecontroller) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(hwdata->gamecontroller, &wireless);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the joystick capabilities */
|
||||||
|
joystick->nbuttons = state->nbuttons;
|
||||||
|
joystick->naxes = state->naxes;
|
||||||
|
joystick->nhats = state->nhats;
|
||||||
|
joystick->epowerlevel = wireless ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
|
||||||
|
|
||||||
|
if (wireless && hwdata->battery) {
|
||||||
|
HRESULT hr;
|
||||||
|
__x_ABI_CWindows_CDevices_CPower_CIBatteryReport *report;
|
||||||
|
|
||||||
|
hr = __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_TryGetBatteryReport(hwdata->battery, &report);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
int full_capacity = 0, curr_capacity = 0;
|
||||||
|
__FIReference_1_int *full_capacityP, *curr_capacityP;
|
||||||
|
|
||||||
|
hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_FullChargeCapacityInMilliwattHours(report, &full_capacityP);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
__FIReference_1_int_get_Value(full_capacityP, &full_capacity);
|
||||||
|
__FIReference_1_int_Release(full_capacityP);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_RemainingCapacityInMilliwattHours(report, &curr_capacityP);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
__FIReference_1_int_get_Value(curr_capacityP, &curr_capacity);
|
||||||
|
__FIReference_1_int_Release(curr_capacityP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (full_capacity > 0) {
|
||||||
|
float ratio = (float)curr_capacity / full_capacity;
|
||||||
|
|
||||||
|
if (ratio <= 0.05f) {
|
||||||
|
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
|
||||||
|
} else if (ratio <= 0.20f) {
|
||||||
|
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
|
||||||
|
} else if (ratio <= 0.70f) {
|
||||||
|
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
|
||||||
|
} else {
|
||||||
|
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__x_ABI_CWindows_CDevices_CPower_CIBatteryReport_Release(report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
WGI_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||||
|
{
|
||||||
|
struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||||
|
|
||||||
|
if (hwdata->gamepad) {
|
||||||
|
HRESULT hr;
|
||||||
|
struct __x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration;
|
||||||
|
|
||||||
|
SDL_zero(vibration);
|
||||||
|
vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
|
||||||
|
vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
|
||||||
|
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(hwdata->gamepad, vibration);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return SDL_SetError("Setting vibration failed: 0x%x\n", hr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint8
|
||||||
|
ConvertHatValue(__x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition value)
|
||||||
|
{
|
||||||
|
switch (value) {
|
||||||
|
case GameControllerSwitchPosition_Up:
|
||||||
|
return SDL_HAT_UP;
|
||||||
|
case GameControllerSwitchPosition_UpRight:
|
||||||
|
return SDL_HAT_RIGHTUP;
|
||||||
|
case GameControllerSwitchPosition_Right:
|
||||||
|
return SDL_HAT_RIGHT;
|
||||||
|
case GameControllerSwitchPosition_DownRight:
|
||||||
|
return SDL_HAT_RIGHTDOWN;
|
||||||
|
case GameControllerSwitchPosition_Down:
|
||||||
|
return SDL_HAT_DOWN;
|
||||||
|
case GameControllerSwitchPosition_DownLeft:
|
||||||
|
return SDL_HAT_LEFTDOWN;
|
||||||
|
case GameControllerSwitchPosition_Left:
|
||||||
|
return SDL_HAT_LEFT;
|
||||||
|
case GameControllerSwitchPosition_UpLeft:
|
||||||
|
return SDL_HAT_LEFTUP;
|
||||||
|
default:
|
||||||
|
return SDL_HAT_CENTERED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WGI_JoystickUpdate(SDL_Joystick * joystick)
|
||||||
|
{
|
||||||
|
struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||||
|
HRESULT hr;
|
||||||
|
UINT32 nbuttons = joystick->nbuttons;
|
||||||
|
boolean *buttons = SDL_stack_alloc(boolean, nbuttons);
|
||||||
|
UINT32 nhats = joystick->nhats;
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition *hats = SDL_stack_alloc(__x_ABI_CWindows_CGaming_CInput_CGameControllerSwitchPosition, nhats);
|
||||||
|
UINT32 naxes = joystick->naxes;
|
||||||
|
DOUBLE *axes = SDL_stack_alloc(DOUBLE, naxes);
|
||||||
|
UINT64 timestamp;
|
||||||
|
|
||||||
|
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_GetCurrentReading(hwdata->controller, nbuttons, buttons, nhats, hats, naxes, axes, ×tamp);
|
||||||
|
if (SUCCEEDED(hr) && timestamp != hwdata->timestamp) {
|
||||||
|
UINT32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < nbuttons; ++i) {
|
||||||
|
SDL_PrivateJoystickButton(joystick, i, buttons[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < nhats; ++i) {
|
||||||
|
SDL_PrivateJoystickHat(joystick, i, ConvertHatValue(hats[i]));
|
||||||
|
}
|
||||||
|
for (i = 0; i < naxes; ++i) {
|
||||||
|
SDL_PrivateJoystickAxis(joystick, i, (int)(axes[i] * 65535) - 32768);
|
||||||
|
}
|
||||||
|
hwdata->timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_stack_free(buttons);
|
||||||
|
SDL_stack_free(hats);
|
||||||
|
SDL_stack_free(axes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WGI_JoystickClose(SDL_Joystick * joystick)
|
||||||
|
{
|
||||||
|
struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||||
|
|
||||||
|
if (hwdata) {
|
||||||
|
if (hwdata->controller) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(hwdata->controller);
|
||||||
|
}
|
||||||
|
if (hwdata->gamecontroller) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGameController_Release(hwdata->gamecontroller);
|
||||||
|
}
|
||||||
|
if (hwdata->battery) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_Release(hwdata->battery);
|
||||||
|
}
|
||||||
|
if (hwdata->gamepad) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(hwdata->gamepad);
|
||||||
|
}
|
||||||
|
SDL_free(hwdata);
|
||||||
|
}
|
||||||
|
joystick->hwdata = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WGI_JoystickQuit(void)
|
||||||
|
{
|
||||||
|
if (wgi.statics) {
|
||||||
|
while (wgi.controller_count > 0) {
|
||||||
|
IEventHandler_CRawGameControllerVtbl_InvokeRemoved(&controller_removed, NULL, (__x_ABI_CWindows_CGaming_CInput_CIRawGameController **)wgi.controllers[wgi.controller_count - 1].controller);
|
||||||
|
}
|
||||||
|
if (wgi.controllers) {
|
||||||
|
SDL_free(wgi.controllers);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wgi.arcade_stick_statics) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_Release(wgi.arcade_stick_statics);
|
||||||
|
}
|
||||||
|
if (wgi.arcade_stick_statics2) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_Release(wgi.arcade_stick_statics2);
|
||||||
|
}
|
||||||
|
if (wgi.flight_stick_statics) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_Release(wgi.flight_stick_statics);
|
||||||
|
}
|
||||||
|
if (wgi.gamepad_statics) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_Release(wgi.gamepad_statics);
|
||||||
|
}
|
||||||
|
if (wgi.gamepad_statics2) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_Release(wgi.gamepad_statics2);
|
||||||
|
}
|
||||||
|
if (wgi.racing_wheel_statics) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_Release(wgi.racing_wheel_statics);
|
||||||
|
}
|
||||||
|
if (wgi.racing_wheel_statics2) {
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_Release(wgi.racing_wheel_statics2);
|
||||||
|
}
|
||||||
|
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerAdded(wgi.statics, wgi.controller_added_token);
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerRemoved(wgi.statics, wgi.controller_removed_token);
|
||||||
|
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.statics);
|
||||||
|
}
|
||||||
|
SDL_zero(wgi);
|
||||||
|
|
||||||
|
WIN_CoUninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_JoystickDriver SDL_WGI_JoystickDriver =
|
||||||
|
{
|
||||||
|
WGI_JoystickInit,
|
||||||
|
WGI_JoystickGetCount,
|
||||||
|
WGI_JoystickDetect,
|
||||||
|
WGI_JoystickGetDeviceName,
|
||||||
|
WGI_JoystickGetDevicePlayerIndex,
|
||||||
|
WGI_JoystickSetDevicePlayerIndex,
|
||||||
|
WGI_JoystickGetDeviceGUID,
|
||||||
|
WGI_JoystickGetDeviceInstanceID,
|
||||||
|
WGI_JoystickOpen,
|
||||||
|
WGI_JoystickRumble,
|
||||||
|
WGI_JoystickUpdate,
|
||||||
|
WGI_JoystickClose,
|
||||||
|
WGI_JoystickQuit,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SDL_JOYSTICK_WGI */
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -41,10 +41,6 @@ DEFINE_GUID(IID_SensorManager, 0xBD77DB67, 0x45A8, 0x42DC, 0x8D, 0x00, 0x6D, 0xC
|
||||||
DEFINE_GUID(IID_SensorManagerEvents, 0x9B3B0B86, 0x266A, 0x4AAD, 0xB2, 0x1F, 0xFD, 0xE5, 0x50, 0x10, 0x01, 0xB7);
|
DEFINE_GUID(IID_SensorManagerEvents, 0x9B3B0B86, 0x266A, 0x4AAD, 0xB2, 0x1F, 0xFD, 0xE5, 0x50, 0x10, 0x01, 0xB7);
|
||||||
DEFINE_GUID(IID_SensorEvents, 0x5D8DCC91, 0x4641, 0x47E7, 0xB7, 0xC3, 0xB7, 0x4F, 0x48, 0xA6, 0xC3, 0x91);
|
DEFINE_GUID(IID_SensorEvents, 0x5D8DCC91, 0x4641, 0x47E7, 0xB7, 0xC3, 0xB7, 0x4F, 0x48, 0xA6, 0xC3, 0x91);
|
||||||
|
|
||||||
DEFINE_PROPERTYKEY(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 10); //[VT_R8]
|
|
||||||
DEFINE_PROPERTYKEY(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 11); //[VT_R8]
|
|
||||||
DEFINE_PROPERTYKEY(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, 0X3F8A69A2, 0X7C5, 0X4E48, 0XA9, 0X65, 0XCD, 0X79, 0X7A, 0XAB, 0X56, 0XD5, 12); //[VT_R8]
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SDL_SensorID id;
|
SDL_SensorID id;
|
||||||
|
|
|
@ -155,6 +155,9 @@ static int s_iCurrentBinding;
|
||||||
static Uint32 s_unPendingAdvanceTime;
|
static Uint32 s_unPendingAdvanceTime;
|
||||||
static SDL_bool s_bBindingComplete;
|
static SDL_bool s_bBindingComplete;
|
||||||
|
|
||||||
|
static SDL_Window *window;
|
||||||
|
static SDL_bool done = SDL_FALSE;
|
||||||
|
|
||||||
SDL_Texture *
|
SDL_Texture *
|
||||||
LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
|
LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
|
||||||
{
|
{
|
||||||
|
@ -357,30 +360,18 @@ BMergeAxisBindings(int iIndex)
|
||||||
static void
|
static void
|
||||||
WatchJoystick(SDL_Joystick * joystick)
|
WatchJoystick(SDL_Joystick * joystick)
|
||||||
{
|
{
|
||||||
SDL_Window *window = NULL;
|
|
||||||
SDL_Renderer *screen = NULL;
|
SDL_Renderer *screen = NULL;
|
||||||
SDL_Texture *background, *button, *axis, *marker;
|
SDL_Texture *background, *button, *axis, *marker;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
SDL_bool done = SDL_FALSE;
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
SDL_Rect dst;
|
SDL_Rect dst;
|
||||||
Uint8 alpha=200, alpha_step = -1;
|
Uint8 alpha=200, alpha_step = -1;
|
||||||
Uint32 alpha_ticks = 0;
|
Uint32 alpha_ticks = 0;
|
||||||
SDL_JoystickID nJoystickID;
|
SDL_JoystickID nJoystickID;
|
||||||
|
|
||||||
/* Create a window to display joystick axis position */
|
|
||||||
window = SDL_CreateWindow("Game Controller Map", SDL_WINDOWPOS_CENTERED,
|
|
||||||
SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
|
|
||||||
SCREEN_HEIGHT, 0);
|
|
||||||
if (window == NULL) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen = SDL_CreateRenderer(window, -1, 0);
|
screen = SDL_CreateRenderer(window, -1, 0);
|
||||||
if (screen == NULL) {
|
if (screen == NULL) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,7 +696,6 @@ WatchJoystick(SDL_Joystick * joystick)
|
||||||
s_arrAxisState = NULL;
|
s_arrAxisState = NULL;
|
||||||
|
|
||||||
SDL_DestroyRenderer(screen);
|
SDL_DestroyRenderer(screen);
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -724,6 +714,34 @@ main(int argc, char *argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a window to display joystick axis position */
|
||||||
|
window = SDL_CreateWindow("Game Controller Map", SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
|
||||||
|
SCREEN_HEIGHT, 0);
|
||||||
|
if (window == NULL) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (SDL_NumJoysticks() == 0) {
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&event) > 0) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if ((event.key.keysym.sym != SDLK_ESCAPE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall through to signal quit */
|
||||||
|
case SDL_QUIT:
|
||||||
|
done = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Print information about the joysticks */
|
/* Print information about the joysticks */
|
||||||
SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
|
SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
|
||||||
for (i = 0; i < SDL_NumJoysticks(); ++i) {
|
for (i = 0; i < SDL_NumJoysticks(); ++i) {
|
||||||
|
@ -748,28 +766,16 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
joystick = SDL_JoystickOpen(0);
|
||||||
if (SDL_NumJoysticks() > 0) {
|
if (joystick == NULL) {
|
||||||
#else
|
SDL_Log("Couldn't open joystick 0: %s\n", SDL_GetError());
|
||||||
if (argv[1]) {
|
} else {
|
||||||
#endif
|
WatchJoystick(joystick);
|
||||||
int device;
|
SDL_JoystickClose(joystick);
|
||||||
#ifdef __ANDROID__
|
|
||||||
device = 0;
|
|
||||||
#else
|
|
||||||
device = atoi(argv[1]);
|
|
||||||
#endif
|
|
||||||
joystick = SDL_JoystickOpen(device);
|
|
||||||
if (joystick == NULL) {
|
|
||||||
SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
|
|
||||||
} else {
|
|
||||||
WatchJoystick(joystick);
|
|
||||||
SDL_JoystickClose(joystick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SDL_Log("\n\nUsage: ./controllermap number\nFor example: ./controllermap 0\nOr: ./controllermap 0 >> gamecontrollerdb.txt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
|
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -61,10 +61,12 @@ static const struct { int x; int y; double angle; } axis_positions[] = {
|
||||||
{375, -20, 0.0}, /* TRIGGERRIGHT */
|
{375, -20, 0.0}, /* TRIGGERRIGHT */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SDL_Window *window = NULL;
|
||||||
SDL_Renderer *screen = NULL;
|
SDL_Renderer *screen = NULL;
|
||||||
SDL_bool retval = SDL_FALSE;
|
SDL_bool retval = SDL_FALSE;
|
||||||
SDL_bool done = SDL_FALSE;
|
SDL_bool done = SDL_FALSE;
|
||||||
SDL_Texture *background, *button, *axis;
|
SDL_Texture *background, *button, *axis;
|
||||||
|
SDL_GameController *gamecontroller;
|
||||||
|
|
||||||
static SDL_Texture *
|
static SDL_Texture *
|
||||||
LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
|
LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
|
||||||
|
@ -94,12 +96,29 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
UpdateWindowTitle()
|
||||||
|
{
|
||||||
|
const char *name = SDL_GameControllerName(gamecontroller);
|
||||||
|
const char *basetitle = "Game Controller Test: ";
|
||||||
|
const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1;
|
||||||
|
char *title = (char *)SDL_malloc(titlelen);
|
||||||
|
|
||||||
|
retval = SDL_FALSE;
|
||||||
|
done = SDL_FALSE;
|
||||||
|
|
||||||
|
if (title) {
|
||||||
|
SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
|
||||||
|
SDL_SetWindowTitle(window, title);
|
||||||
|
SDL_free(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
loop(void *arg)
|
loop(void *arg)
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
int i;
|
int i;
|
||||||
SDL_GameController *gamecontroller = (SDL_GameController *)arg;
|
|
||||||
|
|
||||||
/* blank screen, set up for drawing this frame. */
|
/* blank screen, set up for drawing this frame. */
|
||||||
SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
|
SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
|
||||||
|
@ -108,6 +127,29 @@ loop(void *arg)
|
||||||
|
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
case SDL_CONTROLLERDEVICEADDED:
|
||||||
|
SDL_Log("Game controller device %d added.\n", (int) event.cdevice.which);
|
||||||
|
if (!gamecontroller) {
|
||||||
|
gamecontroller = SDL_GameControllerOpen(event.cdevice.which);
|
||||||
|
if (gamecontroller) {
|
||||||
|
UpdateWindowTitle();
|
||||||
|
} else {
|
||||||
|
SDL_Log("Couldn't open controller: %s\n", SDL_GetError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
|
SDL_Log("Game controller device %d removed.\n", (int) event.cdevice.which);
|
||||||
|
if (gamecontroller && event.cdevice.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) {
|
||||||
|
SDL_GameControllerClose(gamecontroller);
|
||||||
|
gamecontroller = SDL_GameControllerOpen(0);
|
||||||
|
if (gamecontroller) {
|
||||||
|
UpdateWindowTitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SDL_CONTROLLERAXISMOTION:
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
SDL_Log("Controller axis %s changed to %d\n", SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)event.caxis.axis), event.caxis.value);
|
SDL_Log("Controller axis %s changed to %d\n", SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)event.caxis.axis), event.caxis.value);
|
||||||
break;
|
break;
|
||||||
|
@ -128,42 +170,39 @@ loop(void *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update visual controller state */
|
if (gamecontroller) {
|
||||||
for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
|
/* Update visual controller state */
|
||||||
if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
|
for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
|
||||||
const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
|
if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
|
||||||
SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, SDL_FLIP_NONE);
|
const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
|
||||||
|
SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, SDL_FLIP_NONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) {
|
for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) {
|
||||||
const Sint16 deadzone = 8000; /* !!! FIXME: real deadzone */
|
const Sint16 deadzone = 8000; /* !!! FIXME: real deadzone */
|
||||||
const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i));
|
const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i));
|
||||||
if (value < -deadzone) {
|
if (value < -deadzone) {
|
||||||
const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
|
const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
|
||||||
const double angle = axis_positions[i].angle;
|
const double angle = axis_positions[i].angle;
|
||||||
SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
|
SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
|
||||||
} else if (value > deadzone) {
|
} else if (value > deadzone) {
|
||||||
const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
|
const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
|
||||||
const double angle = axis_positions[i].angle + 180.0;
|
const double angle = axis_positions[i].angle + 180.0;
|
||||||
SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
|
SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Update rumble based on trigger state */
|
/* Update rumble based on trigger state */
|
||||||
{
|
{
|
||||||
Uint16 low_frequency_rumble = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) * 2;
|
Uint16 low_frequency_rumble = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) * 2;
|
||||||
Uint16 high_frequency_rumble = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) * 2;
|
Uint16 high_frequency_rumble = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) * 2;
|
||||||
SDL_GameControllerRumble(gamecontroller, low_frequency_rumble, high_frequency_rumble, 250);
|
SDL_GameControllerRumble(gamecontroller, low_frequency_rumble, high_frequency_rumble, 250);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_RenderPresent(screen);
|
SDL_RenderPresent(screen);
|
||||||
|
|
||||||
if (!SDL_GameControllerGetAttached(gamecontroller)) {
|
|
||||||
done = SDL_TRUE;
|
|
||||||
retval = SDL_TRUE; /* keep going, wait for reattach. */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
if (done) {
|
if (done) {
|
||||||
emscripten_cancel_main_loop();
|
emscripten_cancel_main_loop();
|
||||||
|
@ -171,92 +210,12 @@ loop(void *arg)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool
|
|
||||||
WatchGameController(SDL_GameController * gamecontroller)
|
|
||||||
{
|
|
||||||
const char *name = SDL_GameControllerName(gamecontroller);
|
|
||||||
const char *basetitle = "Game Controller Test: ";
|
|
||||||
const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1;
|
|
||||||
char *title = (char *)SDL_malloc(titlelen);
|
|
||||||
SDL_Window *window = NULL;
|
|
||||||
|
|
||||||
retval = SDL_FALSE;
|
|
||||||
done = SDL_FALSE;
|
|
||||||
|
|
||||||
if (title) {
|
|
||||||
SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a window to display controller state */
|
|
||||||
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED,
|
|
||||||
SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
|
|
||||||
SCREEN_HEIGHT, 0);
|
|
||||||
SDL_free(title);
|
|
||||||
title = NULL;
|
|
||||||
if (window == NULL) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen = SDL_CreateRenderer(window, -1, 0);
|
|
||||||
if (screen == NULL) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
|
|
||||||
SDL_RenderClear(screen);
|
|
||||||
SDL_RenderPresent(screen);
|
|
||||||
SDL_RaiseWindow(window);
|
|
||||||
|
|
||||||
/* scale for platforms that don't give you the window size you asked for. */
|
|
||||||
SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
||||||
|
|
||||||
background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
|
|
||||||
button = LoadTexture(screen, "button.bmp", SDL_TRUE);
|
|
||||||
axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
|
|
||||||
|
|
||||||
if (!background || !button || !axis) {
|
|
||||||
SDL_DestroyRenderer(screen);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
SDL_SetTextureColorMod(button, 10, 255, 21);
|
|
||||||
SDL_SetTextureColorMod(axis, 10, 255, 21);
|
|
||||||
|
|
||||||
/* !!! FIXME: */
|
|
||||||
/*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/
|
|
||||||
|
|
||||||
/* Print info about the controller we are watching */
|
|
||||||
SDL_Log("Watching controller %s\n", name ? name : "Unknown Controller");
|
|
||||||
|
|
||||||
/* Loop, getting controller events! */
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
emscripten_set_main_loop_arg(loop, gamecontroller, 0, 1);
|
|
||||||
#else
|
|
||||||
while (!done) {
|
|
||||||
loop(gamecontroller);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_DestroyRenderer(screen);
|
|
||||||
screen = NULL;
|
|
||||||
background = NULL;
|
|
||||||
button = NULL;
|
|
||||||
axis = NULL;
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int nController = 0;
|
int nController = 0;
|
||||||
int retcode = 0;
|
|
||||||
char guid[64];
|
char guid[64];
|
||||||
SDL_GameController *gamecontroller;
|
|
||||||
|
|
||||||
/* Enable standard application logging */
|
/* Enable standard application logging */
|
||||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
|
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
|
||||||
|
@ -270,7 +229,7 @@ main(int argc, char *argv[])
|
||||||
SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
|
SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
|
||||||
|
|
||||||
/* Print information about the mappings */
|
/* Print information about the mappings */
|
||||||
if (!argv[1]) {
|
if (argv[1] && SDL_strcmp(argv[1], "--mappings") == 0) {
|
||||||
SDL_Log("Supported mappings:\n");
|
SDL_Log("Supported mappings:\n");
|
||||||
for (i = 0; i < SDL_GameControllerNumMappings(); ++i) {
|
for (i = 0; i < SDL_GameControllerNumMappings(); ++i) {
|
||||||
char *mapping = SDL_GameControllerMappingForIndex(i);
|
char *mapping = SDL_GameControllerMappingForIndex(i);
|
||||||
|
@ -290,8 +249,7 @@ main(int argc, char *argv[])
|
||||||
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i),
|
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i),
|
||||||
guid, sizeof (guid));
|
guid, sizeof (guid));
|
||||||
|
|
||||||
if ( SDL_IsGameController(i) )
|
if ( SDL_IsGameController(i) ) {
|
||||||
{
|
|
||||||
nController++;
|
nController++;
|
||||||
name = SDL_GameControllerNameForIndex(i);
|
name = SDL_GameControllerNameForIndex(i);
|
||||||
switch (SDL_GameControllerTypeForIndex(i)) {
|
switch (SDL_GameControllerTypeForIndex(i)) {
|
||||||
|
@ -327,62 +285,62 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", nController, SDL_NumJoysticks());
|
SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", nController, SDL_NumJoysticks());
|
||||||
|
|
||||||
if (argv[1]) {
|
/* Create a window to display controller state */
|
||||||
SDL_bool reportederror = SDL_FALSE;
|
window = SDL_CreateWindow("Game Controller Test", SDL_WINDOWPOS_CENTERED,
|
||||||
SDL_bool keepGoing = SDL_TRUE;
|
SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
|
||||||
SDL_Event event;
|
SCREEN_HEIGHT, 0);
|
||||||
int device = atoi(argv[1]);
|
if (window == NULL) {
|
||||||
if (device >= SDL_NumJoysticks()) {
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%i is an invalid joystick index.\n", device);
|
return 2;
|
||||||
retcode = 1;
|
|
||||||
} else {
|
|
||||||
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(device),
|
|
||||||
guid, sizeof (guid));
|
|
||||||
SDL_Log("Attempting to open device %i, guid %s\n", device, guid);
|
|
||||||
gamecontroller = SDL_GameControllerOpen(device);
|
|
||||||
|
|
||||||
if (gamecontroller != NULL) {
|
|
||||||
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (keepGoing) {
|
|
||||||
if (gamecontroller == NULL) {
|
|
||||||
if (!reportederror) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open gamecontroller %d: %s\n", device, SDL_GetError());
|
|
||||||
retcode = 1;
|
|
||||||
keepGoing = SDL_FALSE;
|
|
||||||
reportederror = SDL_TRUE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reportederror = SDL_FALSE;
|
|
||||||
keepGoing = WatchGameController(gamecontroller);
|
|
||||||
SDL_GameControllerClose(gamecontroller);
|
|
||||||
}
|
|
||||||
|
|
||||||
gamecontroller = NULL;
|
|
||||||
if (keepGoing) {
|
|
||||||
SDL_Log("Waiting for attach\n");
|
|
||||||
}
|
|
||||||
while (keepGoing) {
|
|
||||||
SDL_WaitEvent(&event);
|
|
||||||
if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
|
|
||||||
|| (event.type == SDL_MOUSEBUTTONDOWN)) {
|
|
||||||
keepGoing = SDL_FALSE;
|
|
||||||
} else if (event.type == SDL_CONTROLLERDEVICEADDED) {
|
|
||||||
gamecontroller = SDL_GameControllerOpen(event.cdevice.which);
|
|
||||||
if (gamecontroller != NULL) {
|
|
||||||
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
screen = SDL_CreateRenderer(window, -1, 0);
|
||||||
|
if (screen == NULL) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
|
||||||
|
SDL_RenderClear(screen);
|
||||||
|
SDL_RenderPresent(screen);
|
||||||
|
|
||||||
|
/* scale for platforms that don't give you the window size you asked for. */
|
||||||
|
SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
|
||||||
|
button = LoadTexture(screen, "button.bmp", SDL_TRUE);
|
||||||
|
axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
|
||||||
|
|
||||||
|
if (!background || !button || !axis) {
|
||||||
|
SDL_DestroyRenderer(screen);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
SDL_SetTextureColorMod(button, 10, 255, 21);
|
||||||
|
SDL_SetTextureColorMod(axis, 10, 255, 21);
|
||||||
|
|
||||||
|
/* !!! FIXME: */
|
||||||
|
/*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/
|
||||||
|
|
||||||
|
/* Loop, getting controller events! */
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
emscripten_set_main_loop_arg(loop, NULL, 0, 1);
|
||||||
|
#else
|
||||||
|
while (!done) {
|
||||||
|
loop(NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_DestroyRenderer(screen);
|
||||||
|
screen = NULL;
|
||||||
|
background = NULL;
|
||||||
|
button = NULL;
|
||||||
|
axis = NULL;
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
|
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
|
||||||
|
|
||||||
return retcode;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -32,9 +32,62 @@
|
||||||
#define SCREEN_HEIGHT 480
|
#define SCREEN_HEIGHT 480
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_Renderer *screen = NULL;
|
static SDL_Window *window = NULL;
|
||||||
SDL_bool retval = SDL_FALSE;
|
static SDL_Renderer *screen = NULL;
|
||||||
SDL_bool done = SDL_FALSE;
|
static SDL_Joystick *joystick = NULL;
|
||||||
|
static SDL_bool done = SDL_FALSE;
|
||||||
|
|
||||||
|
static void
|
||||||
|
PrintJoystick(SDL_Joystick *joystick)
|
||||||
|
{
|
||||||
|
const char *type;
|
||||||
|
char guid[64];
|
||||||
|
|
||||||
|
SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
|
||||||
|
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), guid, sizeof (guid));
|
||||||
|
switch (SDL_JoystickGetType(joystick)) {
|
||||||
|
case SDL_JOYSTICK_TYPE_GAMECONTROLLER:
|
||||||
|
type = "Game Controller";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_WHEEL:
|
||||||
|
type = "Wheel";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_ARCADE_STICK:
|
||||||
|
type = "Arcade Stick";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_FLIGHT_STICK:
|
||||||
|
type = "Flight Stick";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_DANCE_PAD:
|
||||||
|
type = "Dance Pad";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_GUITAR:
|
||||||
|
type = "Guitar";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_DRUM_KIT:
|
||||||
|
type = "Drum Kit";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_ARCADE_PAD:
|
||||||
|
type = "Arcade Pad";
|
||||||
|
break;
|
||||||
|
case SDL_JOYSTICK_TYPE_THROTTLE:
|
||||||
|
type = "Throttle";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SDL_Log("Joystick\n");
|
||||||
|
SDL_Log(" name: %s\n", SDL_JoystickName(joystick));
|
||||||
|
SDL_Log(" type: %s\n", type);
|
||||||
|
SDL_Log(" axes: %d\n", SDL_JoystickNumAxes(joystick));
|
||||||
|
SDL_Log(" balls: %d\n", SDL_JoystickNumBalls(joystick));
|
||||||
|
SDL_Log(" hats: %d\n", SDL_JoystickNumHats(joystick));
|
||||||
|
SDL_Log(" buttons: %d\n", SDL_JoystickNumButtons(joystick));
|
||||||
|
SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
|
||||||
|
SDL_Log(" guid: %s\n", guid);
|
||||||
|
SDL_Log(" VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
|
DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
|
||||||
|
@ -48,72 +101,89 @@ loop(void *arg)
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
int i;
|
int i;
|
||||||
SDL_Joystick *joystick = (SDL_Joystick *)arg;
|
|
||||||
|
|
||||||
/* blank screen, set up for drawing this frame. */
|
/* blank screen, set up for drawing this frame. */
|
||||||
SDL_SetRenderDrawColor(screen, 0x0, 0x0, 0x0, SDL_ALPHA_OPAQUE);
|
SDL_SetRenderDrawColor(screen, 0x0, 0x0, 0x0, SDL_ALPHA_OPAQUE);
|
||||||
SDL_RenderClear(screen);
|
SDL_RenderClear(screen);
|
||||||
|
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
|
||||||
case SDL_JOYDEVICEREMOVED:
|
case SDL_JOYDEVICEADDED:
|
||||||
SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which);
|
SDL_Log("Joystick device %d added.\n", (int) event.jdevice.which);
|
||||||
SDL_Log("Our instance ID is %d\n", (int) SDL_JoystickInstanceID(joystick));
|
if (!joystick) {
|
||||||
break;
|
joystick = SDL_JoystickOpen(event.jdevice.which);
|
||||||
|
if (joystick) {
|
||||||
case SDL_JOYAXISMOTION:
|
PrintJoystick(joystick);
|
||||||
SDL_Log("Joystick %d axis %d value: %d\n",
|
} else {
|
||||||
event.jaxis.which,
|
SDL_Log("Couldn't open joystick: %s\n", SDL_GetError());
|
||||||
event.jaxis.axis, event.jaxis.value);
|
|
||||||
break;
|
|
||||||
case SDL_JOYHATMOTION:
|
|
||||||
SDL_Log("Joystick %d hat %d value:",
|
|
||||||
event.jhat.which, event.jhat.hat);
|
|
||||||
if (event.jhat.value == SDL_HAT_CENTERED)
|
|
||||||
SDL_Log(" centered");
|
|
||||||
if (event.jhat.value & SDL_HAT_UP)
|
|
||||||
SDL_Log(" up");
|
|
||||||
if (event.jhat.value & SDL_HAT_RIGHT)
|
|
||||||
SDL_Log(" right");
|
|
||||||
if (event.jhat.value & SDL_HAT_DOWN)
|
|
||||||
SDL_Log(" down");
|
|
||||||
if (event.jhat.value & SDL_HAT_LEFT)
|
|
||||||
SDL_Log(" left");
|
|
||||||
SDL_Log("\n");
|
|
||||||
break;
|
|
||||||
case SDL_JOYBALLMOTION:
|
|
||||||
SDL_Log("Joystick %d ball %d delta: (%d,%d)\n",
|
|
||||||
event.jball.which,
|
|
||||||
event.jball.ball, event.jball.xrel, event.jball.yrel);
|
|
||||||
break;
|
|
||||||
case SDL_JOYBUTTONDOWN:
|
|
||||||
SDL_Log("Joystick %d button %d down\n",
|
|
||||||
event.jbutton.which, event.jbutton.button);
|
|
||||||
/* First button triggers a 0.5 second full strength rumble */
|
|
||||||
if (event.jbutton.button == 0) {
|
|
||||||
SDL_JoystickRumble(joystick, 0xFFFF, 0xFFFF, 500);
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case SDL_JOYBUTTONUP:
|
break;
|
||||||
SDL_Log("Joystick %d button %d up\n",
|
|
||||||
event.jbutton.which, event.jbutton.button);
|
case SDL_JOYDEVICEREMOVED:
|
||||||
break;
|
SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which);
|
||||||
case SDL_KEYDOWN:
|
if (event.jdevice.which == SDL_JoystickInstanceID(joystick)) {
|
||||||
if ((event.key.keysym.sym != SDLK_ESCAPE) &&
|
SDL_JoystickClose(joystick);
|
||||||
(event.key.keysym.sym != SDLK_AC_BACK)) {
|
joystick = SDL_JoystickOpen(0);
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
/* Fall through to signal quit */
|
|
||||||
case SDL_FINGERDOWN:
|
case SDL_JOYAXISMOTION:
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
SDL_Log("Joystick %d axis %d value: %d\n",
|
||||||
case SDL_QUIT:
|
event.jaxis.which,
|
||||||
done = SDL_TRUE;
|
event.jaxis.axis, event.jaxis.value);
|
||||||
break;
|
break;
|
||||||
default:
|
case SDL_JOYHATMOTION:
|
||||||
|
SDL_Log("Joystick %d hat %d value:",
|
||||||
|
event.jhat.which, event.jhat.hat);
|
||||||
|
if (event.jhat.value == SDL_HAT_CENTERED)
|
||||||
|
SDL_Log(" centered");
|
||||||
|
if (event.jhat.value & SDL_HAT_UP)
|
||||||
|
SDL_Log(" up");
|
||||||
|
if (event.jhat.value & SDL_HAT_RIGHT)
|
||||||
|
SDL_Log(" right");
|
||||||
|
if (event.jhat.value & SDL_HAT_DOWN)
|
||||||
|
SDL_Log(" down");
|
||||||
|
if (event.jhat.value & SDL_HAT_LEFT)
|
||||||
|
SDL_Log(" left");
|
||||||
|
SDL_Log("\n");
|
||||||
|
break;
|
||||||
|
case SDL_JOYBALLMOTION:
|
||||||
|
SDL_Log("Joystick %d ball %d delta: (%d,%d)\n",
|
||||||
|
event.jball.which,
|
||||||
|
event.jball.ball, event.jball.xrel, event.jball.yrel);
|
||||||
|
break;
|
||||||
|
case SDL_JOYBUTTONDOWN:
|
||||||
|
SDL_Log("Joystick %d button %d down\n",
|
||||||
|
event.jbutton.which, event.jbutton.button);
|
||||||
|
/* First button triggers a 0.5 second full strength rumble */
|
||||||
|
if (event.jbutton.button == 0) {
|
||||||
|
SDL_JoystickRumble(joystick, 0xFFFF, 0xFFFF, 500);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_JOYBUTTONUP:
|
||||||
|
SDL_Log("Joystick %d button %d up\n",
|
||||||
|
event.jbutton.which, event.jbutton.button);
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if ((event.key.keysym.sym != SDLK_ESCAPE) &&
|
||||||
|
(event.key.keysym.sym != SDLK_AC_BACK)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* Fall through to signal quit */
|
||||||
|
case SDL_FINGERDOWN:
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
case SDL_QUIT:
|
||||||
|
done = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joystick) {
|
||||||
|
|
||||||
/* Update visual joystick state */
|
/* Update visual joystick state */
|
||||||
SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
|
SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
|
||||||
for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
|
for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
|
||||||
|
@ -172,13 +242,9 @@ loop(void *arg)
|
||||||
|
|
||||||
DrawRect(screen, x, y, 8, 8);
|
DrawRect(screen, x, y, 8, 8);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SDL_RenderPresent(screen);
|
SDL_RenderPresent(screen);
|
||||||
|
|
||||||
if (SDL_JoystickGetAttached( joystick ) == 0) {
|
|
||||||
done = SDL_TRUE;
|
|
||||||
retval = SDL_TRUE; /* keep going, wait for reattach. */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
if (done) {
|
if (done) {
|
||||||
|
@ -187,14 +253,19 @@ loop(void *arg)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool
|
int
|
||||||
WatchJoystick(SDL_Joystick * joystick)
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
SDL_Window *window = NULL;
|
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
||||||
const char *name = NULL;
|
|
||||||
|
|
||||||
retval = SDL_FALSE;
|
/* Enable standard application logging */
|
||||||
done = SDL_FALSE;
|
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
|
||||||
|
|
||||||
|
/* Initialize SDL (Note: video is required to start event loop) */
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a window to display joystick axis position */
|
/* Create a window to display joystick axis position */
|
||||||
window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
|
window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
|
||||||
|
@ -215,159 +286,19 @@ WatchJoystick(SDL_Joystick * joystick)
|
||||||
SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
|
SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
|
||||||
SDL_RenderClear(screen);
|
SDL_RenderClear(screen);
|
||||||
SDL_RenderPresent(screen);
|
SDL_RenderPresent(screen);
|
||||||
SDL_RaiseWindow(window);
|
|
||||||
|
|
||||||
/* Print info about the joystick we are watching */
|
|
||||||
name = SDL_JoystickName(joystick);
|
|
||||||
SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
|
|
||||||
name ? name : "Unknown Joystick");
|
|
||||||
SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
|
|
||||||
SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
|
|
||||||
SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
|
|
||||||
|
|
||||||
/* Loop, getting joystick events! */
|
/* Loop, getting joystick events! */
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
emscripten_set_main_loop_arg(loop, joystick, 0, 1);
|
emscripten_set_main_loop_arg(loop, NULL, 0, 1);
|
||||||
#else
|
#else
|
||||||
while (!done) {
|
while (!done) {
|
||||||
loop(joystick);
|
loop(NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_DestroyRenderer(screen);
|
SDL_DestroyRenderer(screen);
|
||||||
screen = NULL;
|
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
const char *name, *type;
|
|
||||||
int i;
|
|
||||||
SDL_Joystick *joystick;
|
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
|
||||||
|
|
||||||
/* Enable standard application logging */
|
|
||||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
|
|
||||||
|
|
||||||
/* Initialize SDL (Note: video is required to start event loop) */
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print information about the joysticks */
|
|
||||||
SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
|
|
||||||
for (i = 0; i < SDL_NumJoysticks(); ++i) {
|
|
||||||
name = SDL_JoystickNameForIndex(i);
|
|
||||||
SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
|
|
||||||
joystick = SDL_JoystickOpen(i);
|
|
||||||
if (joystick == NULL) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
|
|
||||||
SDL_GetError());
|
|
||||||
} else {
|
|
||||||
char guid[64];
|
|
||||||
SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
|
|
||||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
|
|
||||||
guid, sizeof (guid));
|
|
||||||
switch (SDL_JoystickGetType(joystick)) {
|
|
||||||
case SDL_JOYSTICK_TYPE_GAMECONTROLLER:
|
|
||||||
type = "Game Controller";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_WHEEL:
|
|
||||||
type = "Wheel";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_ARCADE_STICK:
|
|
||||||
type = "Arcade Stick";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_FLIGHT_STICK:
|
|
||||||
type = "Flight Stick";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_DANCE_PAD:
|
|
||||||
type = "Dance Pad";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_GUITAR:
|
|
||||||
type = "Guitar";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_DRUM_KIT:
|
|
||||||
type = "Drum Kit";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_ARCADE_PAD:
|
|
||||||
type = "Arcade Pad";
|
|
||||||
break;
|
|
||||||
case SDL_JOYSTICK_TYPE_THROTTLE:
|
|
||||||
type = "Throttle";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
type = "Unknown";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SDL_Log(" type: %s\n", type);
|
|
||||||
SDL_Log(" axes: %d\n", SDL_JoystickNumAxes(joystick));
|
|
||||||
SDL_Log(" balls: %d\n", SDL_JoystickNumBalls(joystick));
|
|
||||||
SDL_Log(" hats: %d\n", SDL_JoystickNumHats(joystick));
|
|
||||||
SDL_Log(" buttons: %d\n", SDL_JoystickNumButtons(joystick));
|
|
||||||
SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
|
|
||||||
SDL_Log(" guid: %s\n", guid);
|
|
||||||
SDL_Log(" VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick));
|
|
||||||
SDL_JoystickClose(joystick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__ANDROID__) || defined(__IPHONEOS__)
|
|
||||||
if (SDL_NumJoysticks() > 0) {
|
|
||||||
#else
|
|
||||||
if (argv[1]) {
|
|
||||||
#endif
|
|
||||||
SDL_bool reportederror = SDL_FALSE;
|
|
||||||
SDL_bool keepGoing = SDL_TRUE;
|
|
||||||
SDL_Event event;
|
|
||||||
int device;
|
|
||||||
#if defined(__ANDROID__) || defined(__IPHONEOS__)
|
|
||||||
device = 0;
|
|
||||||
#else
|
|
||||||
device = atoi(argv[1]);
|
|
||||||
#endif
|
|
||||||
joystick = SDL_JoystickOpen(device);
|
|
||||||
if (joystick != NULL) {
|
|
||||||
SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( keepGoing ) {
|
|
||||||
if (joystick == NULL) {
|
|
||||||
if ( !reportederror ) {
|
|
||||||
SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
|
|
||||||
keepGoing = SDL_FALSE;
|
|
||||||
reportederror = SDL_TRUE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reportederror = SDL_FALSE;
|
|
||||||
keepGoing = WatchJoystick(joystick);
|
|
||||||
SDL_JoystickClose(joystick);
|
|
||||||
}
|
|
||||||
|
|
||||||
joystick = NULL;
|
|
||||||
if (keepGoing) {
|
|
||||||
SDL_Log("Waiting for attach\n");
|
|
||||||
}
|
|
||||||
while (keepGoing) {
|
|
||||||
SDL_WaitEvent(&event);
|
|
||||||
if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
|
|
||||||
|| (event.type == SDL_MOUSEBUTTONDOWN)) {
|
|
||||||
keepGoing = SDL_FALSE;
|
|
||||||
} else if (event.type == SDL_JOYDEVICEADDED) {
|
|
||||||
device = event.jdevice.which;
|
|
||||||
joystick = SDL_JoystickOpen(device);
|
|
||||||
if (joystick != NULL) {
|
|
||||||
SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
|
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue