2015-06-21 15:33:46 +00:00
|
|
|
/*
|
|
|
|
Simple DirectMedia Layer
|
2021-01-02 18:25:38 +00:00
|
|
|
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*/
|
|
|
|
#include "../../SDL_internal.h"
|
|
|
|
|
|
|
|
#if SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT
|
|
|
|
|
|
|
|
/* 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 IDirectInputDevice8_GetDeviceData and
|
|
|
|
* let it return 0 events. */
|
|
|
|
|
|
|
|
#include "SDL_error.h"
|
|
|
|
#include "SDL_events.h"
|
2020-12-13 06:08:02 +00:00
|
|
|
#include "SDL_hints.h"
|
2015-06-21 15:33:46 +00:00
|
|
|
#include "SDL_timer.h"
|
|
|
|
#include "SDL_mutex.h"
|
|
|
|
#include "SDL_joystick.h"
|
|
|
|
#include "../SDL_sysjoystick.h"
|
2016-04-12 22:11:36 +00:00
|
|
|
#include "../../thread/SDL_systhread.h"
|
2015-06-21 15:33:46 +00:00
|
|
|
#include "../../core/windows/SDL_windows.h"
|
|
|
|
#if !defined(__WINRT__)
|
|
|
|
#include <dbt.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
|
|
|
|
#include "SDL_windowsjoystick_c.h"
|
|
|
|
#include "SDL_dinputjoystick_c.h"
|
|
|
|
#include "SDL_xinputjoystick_c.h"
|
2020-11-27 21:08:40 +00:00
|
|
|
#include "SDL_rawinputjoystick_c.h"
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
#include "../../haptic/windows/SDL_dinputhaptic_c.h" /* For haptic hot plugging */
|
|
|
|
#include "../../haptic/windows/SDL_xinputhaptic_c.h" /* For haptic hot plugging */
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef DEVICE_NOTIFY_WINDOW_HANDLE
|
|
|
|
#define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000
|
|
|
|
#endif
|
|
|
|
|
2021-07-24 06:45:18 +00:00
|
|
|
/* CM_Register_Notification definitions */
|
|
|
|
|
|
|
|
#define CR_SUCCESS (0x00000000)
|
|
|
|
|
|
|
|
DECLARE_HANDLE(HCMNOTIFICATION);
|
|
|
|
typedef HCMNOTIFICATION* PHCMNOTIFICATION;
|
|
|
|
|
|
|
|
typedef enum _CM_NOTIFY_FILTER_TYPE {
|
|
|
|
CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE = 0,
|
|
|
|
CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE,
|
|
|
|
CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE,
|
|
|
|
CM_NOTIFY_FILTER_TYPE_MAX
|
|
|
|
} CM_NOTIFY_FILTER_TYPE, * PCM_NOTIFY_FILTER_TYPE;
|
|
|
|
|
|
|
|
typedef struct _CM_NOTIFY_FILTER {
|
|
|
|
DWORD cbSize;
|
|
|
|
DWORD Flags;
|
|
|
|
CM_NOTIFY_FILTER_TYPE FilterType;
|
|
|
|
DWORD Reserved;
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
GUID ClassGuid;
|
|
|
|
} DeviceInterface;
|
|
|
|
struct {
|
|
|
|
HANDLE hTarget;
|
|
|
|
} DeviceHandle;
|
|
|
|
struct {
|
|
|
|
WCHAR InstanceId[200];
|
|
|
|
} DeviceInstance;
|
|
|
|
} u;
|
|
|
|
} CM_NOTIFY_FILTER, * PCM_NOTIFY_FILTER;
|
|
|
|
|
|
|
|
typedef enum _CM_NOTIFY_ACTION {
|
|
|
|
CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL = 0,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEQUERYREMOVE,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEREMOVEPENDING,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE,
|
|
|
|
CM_NOTIFY_ACTION_DEVICECUSTOMEVENT,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEINSTANCEENUMERATED,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEINSTANCESTARTED,
|
|
|
|
CM_NOTIFY_ACTION_DEVICEINSTANCEREMOVED,
|
|
|
|
CM_NOTIFY_ACTION_MAX
|
|
|
|
} CM_NOTIFY_ACTION, * PCM_NOTIFY_ACTION;
|
|
|
|
|
|
|
|
typedef struct _CM_NOTIFY_EVENT_DATA {
|
|
|
|
CM_NOTIFY_FILTER_TYPE FilterType;
|
|
|
|
DWORD Reserved;
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
GUID ClassGuid;
|
|
|
|
WCHAR SymbolicLink[ANYSIZE_ARRAY];
|
|
|
|
} DeviceInterface;
|
|
|
|
struct {
|
|
|
|
GUID EventGuid;
|
|
|
|
LONG NameOffset;
|
|
|
|
DWORD DataSize;
|
|
|
|
BYTE Data[ANYSIZE_ARRAY];
|
|
|
|
} DeviceHandle;
|
|
|
|
struct {
|
|
|
|
WCHAR InstanceId[ANYSIZE_ARRAY];
|
|
|
|
} DeviceInstance;
|
|
|
|
} u;
|
|
|
|
} CM_NOTIFY_EVENT_DATA, * PCM_NOTIFY_EVENT_DATA;
|
|
|
|
|
|
|
|
typedef DWORD (CALLBACK *PCM_NOTIFY_CALLBACK)(HCMNOTIFICATION hNotify, PVOID Context, CM_NOTIFY_ACTION Action, PCM_NOTIFY_EVENT_DATA EventData, DWORD EventDataSize);
|
|
|
|
|
|
|
|
typedef DWORD (WINAPI *CM_Register_NotificationFunc)(PCM_NOTIFY_FILTER pFilter, PVOID pContext, PCM_NOTIFY_CALLBACK pCallback, PHCMNOTIFICATION pNotifyContext);
|
|
|
|
typedef DWORD (WINAPI *CM_Unregister_NotificationFunc)(HCMNOTIFICATION NotifyContext);
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
/* local variables */
|
2020-12-13 06:08:02 +00:00
|
|
|
static SDL_bool s_bJoystickThread = SDL_FALSE;
|
2020-12-18 21:10:36 +00:00
|
|
|
static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
static SDL_cond *s_condJoystickThread = NULL;
|
|
|
|
static SDL_mutex *s_mutexJoyStickEnum = NULL;
|
2020-12-13 06:08:02 +00:00
|
|
|
static SDL_Thread *s_joystickThread = NULL;
|
2015-06-21 15:33:46 +00:00
|
|
|
static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
|
2021-07-24 06:45:18 +00:00
|
|
|
static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
|
|
|
|
|
2021-08-03 09:02:32 +00:00
|
|
|
#ifndef __WINRT__
|
2021-07-24 06:45:18 +00:00
|
|
|
static HMODULE cfgmgr32_lib_handle;
|
|
|
|
static CM_Register_NotificationFunc CM_Register_Notification;
|
|
|
|
static CM_Unregister_NotificationFunc CM_Unregister_Notification;
|
|
|
|
static HCMNOTIFICATION s_DeviceNotificationFuncHandle;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2021-07-24 06:45:18 +00:00
|
|
|
static DWORD CALLBACK
|
|
|
|
SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID context, CM_NOTIFY_ACTION action, PCM_NOTIFY_EVENT_DATA eventData, DWORD event_data_size)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2021-07-24 06:45:18 +00:00
|
|
|
if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL ||
|
|
|
|
action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) {
|
|
|
|
s_bWindowsDeviceChanged = SDL_TRUE;
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 06:45:18 +00:00
|
|
|
static void
|
|
|
|
SDL_CleanupDeviceNotificationFunc(void)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2021-07-24 06:45:18 +00:00
|
|
|
if (cfgmgr32_lib_handle) {
|
|
|
|
if (s_DeviceNotificationFuncHandle) {
|
|
|
|
CM_Unregister_Notification(s_DeviceNotificationFuncHandle);
|
|
|
|
s_DeviceNotificationFuncHandle = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeLibrary(cfgmgr32_lib_handle);
|
|
|
|
cfgmgr32_lib_handle = NULL;
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2017-09-08 14:15:47 +00:00
|
|
|
static SDL_bool
|
2021-07-24 06:45:18 +00:00
|
|
|
SDL_CreateDeviceNotificationFunc(void)
|
|
|
|
{
|
|
|
|
cfgmgr32_lib_handle = LoadLibraryA("cfgmgr32.dll");
|
|
|
|
if (cfgmgr32_lib_handle) {
|
|
|
|
CM_Register_Notification = (CM_Register_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Register_Notification");
|
|
|
|
CM_Unregister_Notification = (CM_Unregister_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Unregister_Notification");
|
|
|
|
if (CM_Register_Notification && CM_Unregister_Notification) {
|
|
|
|
CM_NOTIFY_FILTER notify_filter;
|
|
|
|
|
|
|
|
SDL_zero(notify_filter);
|
|
|
|
notify_filter.cbSize = sizeof(notify_filter);
|
|
|
|
notify_filter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
|
|
|
|
notify_filter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_HID;
|
|
|
|
if (CM_Register_Notification(¬ify_filter, NULL, SDL_DeviceNotificationFunc, &s_DeviceNotificationFuncHandle) == CR_SUCCESS) {
|
|
|
|
return SDL_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_CleanupDeviceNotificationFunc();
|
2017-09-08 14:15:47 +00:00
|
|
|
return SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
HRESULT coinitialized;
|
|
|
|
WNDCLASSEX wincl;
|
|
|
|
HWND messageWindow;
|
|
|
|
HDEVNOTIFY hNotify;
|
|
|
|
} SDL_DeviceNotificationData;
|
|
|
|
|
2017-09-08 14:15:47 +00:00
|
|
|
#define IDT_SDL_DEVICE_CHANGE_TIMER_1 1200
|
|
|
|
#define IDT_SDL_DEVICE_CHANGE_TIMER_2 1201
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
|
|
|
|
static LRESULT CALLBACK
|
2020-11-27 21:08:40 +00:00
|
|
|
SDL_PrivateJoystickDetectProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2020-11-27 21:08:40 +00:00
|
|
|
switch (msg) {
|
2015-06-21 15:33:46 +00:00
|
|
|
case WM_DEVICECHANGE:
|
|
|
|
switch (wParam) {
|
|
|
|
case DBT_DEVICEARRIVAL:
|
|
|
|
case DBT_DEVICEREMOVECOMPLETE:
|
|
|
|
if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
|
2017-09-08 14:15:47 +00:00
|
|
|
/* notify 300ms and 2 seconds later to ensure all APIs have updated status */
|
|
|
|
SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_1, 300, NULL);
|
|
|
|
SetTimer(hwnd, IDT_SDL_DEVICE_CHANGE_TIMER_2, 2000, NULL);
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
2017-09-08 14:15:47 +00:00
|
|
|
case WM_TIMER:
|
2020-12-18 21:10:36 +00:00
|
|
|
if (wParam == IDT_SDL_DEVICE_CHANGE_TIMER_1 ||
|
|
|
|
wParam == IDT_SDL_DEVICE_CHANGE_TIMER_2) {
|
|
|
|
KillTimer(hwnd, wParam);
|
|
|
|
s_bWindowsDeviceChanged = SDL_TRUE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2020-11-27 21:08:40 +00:00
|
|
|
#if SDL_JOYSTICK_RAWINPUT
|
|
|
|
return CallWindowProc(RAWINPUT_WindowProc, hwnd, msg, wParam, lParam);
|
|
|
|
#else
|
|
|
|
return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
|
|
|
|
#endif
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
|
|
|
|
{
|
2020-11-27 21:08:40 +00:00
|
|
|
#if SDL_JOYSTICK_RAWINPUT
|
|
|
|
RAWINPUT_UnregisterNotifications();
|
|
|
|
#endif
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
if (data->hNotify)
|
|
|
|
UnregisterDeviceNotification(data->hNotify);
|
|
|
|
|
|
|
|
if (data->messageWindow)
|
|
|
|
DestroyWindow(data->messageWindow);
|
|
|
|
|
|
|
|
UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
|
|
|
|
|
|
|
|
if (data->coinitialized == S_OK) {
|
|
|
|
WIN_CoUninitialize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
|
|
|
|
{
|
|
|
|
DEV_BROADCAST_DEVICEINTERFACE dbh;
|
|
|
|
|
|
|
|
SDL_zerop(data);
|
|
|
|
|
|
|
|
data->coinitialized = WIN_CoInitialize();
|
|
|
|
|
|
|
|
data->wincl.hInstance = GetModuleHandle(NULL);
|
2021-01-03 22:23:50 +00:00
|
|
|
data->wincl.lpszClassName = TEXT("Message");
|
2015-06-21 15:33:46 +00:00
|
|
|
data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; /* This function is called by windows */
|
|
|
|
data->wincl.cbSize = sizeof (WNDCLASSEX);
|
|
|
|
|
|
|
|
if (!RegisterClassEx(&data->wincl)) {
|
|
|
|
WIN_SetError("Failed to create register class for joystick autodetect");
|
|
|
|
SDL_CleanupDeviceNotification(data);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-01-03 22:23:50 +00:00
|
|
|
data->messageWindow = (HWND)CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
|
2015-06-21 15:33:46 +00:00
|
|
|
if (!data->messageWindow) {
|
|
|
|
WIN_SetError("Failed to create message window for joystick autodetect");
|
|
|
|
SDL_CleanupDeviceNotification(data);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_zero(dbh);
|
|
|
|
dbh.dbcc_size = sizeof(dbh);
|
|
|
|
dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
|
|
dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
|
|
|
|
|
|
|
data->hNotify = RegisterDeviceNotification(data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
|
|
if (!data->hNotify) {
|
|
|
|
WIN_SetError("Failed to create notify device for joystick autodetect");
|
|
|
|
SDL_CleanupDeviceNotification(data);
|
|
|
|
return -1;
|
|
|
|
}
|
2020-11-27 21:08:40 +00:00
|
|
|
|
|
|
|
#if SDL_JOYSTICK_RAWINPUT
|
|
|
|
RAWINPUT_RegisterNotifications(data->messageWindow);
|
|
|
|
#endif
|
2015-06-21 15:33:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-08 14:15:47 +00:00
|
|
|
static SDL_bool
|
|
|
|
SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, SDL_mutex *mutex)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
MSG msg;
|
2017-09-08 14:15:47 +00:00
|
|
|
int lastret = 1;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
if (!data->messageWindow) {
|
2017-09-08 14:15:47 +00:00
|
|
|
return SDL_FALSE; /* device notifications require a window */
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2017-09-08 14:15:47 +00:00
|
|
|
SDL_UnlockMutex(mutex);
|
|
|
|
while (lastret > 0 && s_bWindowsDeviceChanged == SDL_FALSE) {
|
|
|
|
lastret = GetMessage(&msg, NULL, 0, 0); /* WM_QUIT causes return value of 0 */
|
|
|
|
if (lastret > 0) {
|
2015-06-21 15:33:46 +00:00
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessage(&msg);
|
|
|
|
}
|
|
|
|
}
|
2017-09-08 14:15:47 +00:00
|
|
|
SDL_LockMutex(mutex);
|
|
|
|
return (lastret != -1) ? SDL_TRUE : SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2020-12-13 06:08:02 +00:00
|
|
|
static SDL_DeviceNotificationData s_notification_data;
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
/* Function/thread to scan the system for joysticks. */
|
|
|
|
static int
|
|
|
|
SDL_JoystickThread(void *_data)
|
|
|
|
{
|
|
|
|
#if SDL_JOYSTICK_XINPUT
|
|
|
|
SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
|
2019-07-31 02:11:40 +00:00
|
|
|
SDL_zeroa(bOpenedXInputDevices);
|
2015-06-21 15:33:46 +00:00
|
|
|
#endif
|
|
|
|
|
2020-12-13 06:08:02 +00:00
|
|
|
if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
|
2015-06-21 15:33:46 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_LockMutex(s_mutexJoyStickEnum);
|
|
|
|
while (s_bJoystickThreadQuit == SDL_FALSE) {
|
2020-12-13 06:08:02 +00:00
|
|
|
if (SDL_WaitForDeviceNotification(&s_notification_data, s_mutexJoyStickEnum) == SDL_FALSE) {
|
2015-06-21 15:33:46 +00:00
|
|
|
#if SDL_JOYSTICK_XINPUT
|
2017-09-08 14:15:47 +00:00
|
|
|
/* WM_DEVICECHANGE not working, poll for new XINPUT controllers */
|
|
|
|
SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 1000);
|
|
|
|
if (SDL_XINPUT_Enabled() && XINPUTGETCAPABILITIES) {
|
|
|
|
/* scan for any change in XInput devices */
|
|
|
|
Uint8 userId;
|
|
|
|
for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
|
|
|
|
XINPUT_CAPABILITIES capabilities;
|
|
|
|
const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
|
|
|
|
const SDL_bool available = (result == ERROR_SUCCESS);
|
|
|
|
if (bOpenedXInputDevices[userId] != available) {
|
2020-12-18 21:10:36 +00:00
|
|
|
s_bWindowsDeviceChanged = SDL_TRUE;
|
2017-09-08 14:15:47 +00:00
|
|
|
bOpenedXInputDevices[userId] = available;
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
2017-09-08 14:15:47 +00:00
|
|
|
#else
|
|
|
|
/* WM_DEVICECHANGE not working, no XINPUT, no point in keeping thread alive */
|
|
|
|
break;
|
2015-06-21 15:33:46 +00:00
|
|
|
#endif /* SDL_JOYSTICK_XINPUT */
|
2018-09-24 18:49:25 +00:00
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
|
|
|
|
2020-12-13 06:08:02 +00:00
|
|
|
SDL_CleanupDeviceNotification(&s_notification_data);
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-13 06:08:02 +00:00
|
|
|
/* spin up the thread to detect hotplug of devices */
|
|
|
|
static int
|
|
|
|
SDL_StartJoystickThread(void)
|
|
|
|
{
|
|
|
|
s_mutexJoyStickEnum = SDL_CreateMutex();
|
|
|
|
if (!s_mutexJoyStickEnum) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_condJoystickThread = SDL_CreateCond();
|
|
|
|
if (!s_condJoystickThread) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_bJoystickThreadQuit = SDL_FALSE;
|
|
|
|
s_joystickThread = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
|
|
|
|
if (!s_joystickThread) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SDL_StopJoystickThread(void)
|
|
|
|
{
|
|
|
|
if (!s_joystickThread) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_LockMutex(s_mutexJoyStickEnum);
|
|
|
|
s_bJoystickThreadQuit = SDL_TRUE;
|
|
|
|
SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
|
|
|
|
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
|
|
|
PostThreadMessage(SDL_GetThreadID(s_joystickThread), WM_QUIT, 0, 0);
|
|
|
|
SDL_WaitThread(s_joystickThread, NULL); /* wait for it to bugger off */
|
|
|
|
|
|
|
|
SDL_DestroyCond(s_condJoystickThread);
|
|
|
|
s_condJoystickThread = NULL;
|
|
|
|
|
|
|
|
SDL_DestroyMutex(s_mutexJoyStickEnum);
|
|
|
|
s_mutexJoyStickEnum = NULL;
|
|
|
|
|
|
|
|
s_joystickThread = NULL;
|
|
|
|
}
|
|
|
|
|
2021-07-24 06:45:18 +00:00
|
|
|
#endif /* !__WINRT__ */
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
device->send_add_event = SDL_TRUE;
|
2018-08-09 23:00:17 +00:00
|
|
|
device->nInstanceID = SDL_GetNextJoystickInstanceID();
|
2015-06-21 15:33:46 +00:00
|
|
|
device->pNext = SYS_Joystick;
|
|
|
|
SYS_Joystick = device;
|
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
static void WINDOWS_JoystickDetect(void);
|
|
|
|
static void WINDOWS_JoystickQuit(void);
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
/* Function to scan the system for joysticks.
|
|
|
|
* Joystick 0 should be the system default joystick.
|
|
|
|
* It should return 0, or -1 on an unrecoverable fatal error.
|
|
|
|
*/
|
2018-08-09 23:00:17 +00:00
|
|
|
static int
|
|
|
|
WINDOWS_JoystickInit(void)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
if (SDL_DINPUT_JoystickInit() < 0) {
|
2018-08-09 23:00:17 +00:00
|
|
|
WINDOWS_JoystickQuit();
|
2015-06-21 15:33:46 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SDL_XINPUT_JoystickInit() < 0) {
|
2018-08-09 23:00:17 +00:00
|
|
|
WINDOWS_JoystickQuit();
|
2015-06-21 15:33:46 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-12-18 21:10:36 +00:00
|
|
|
s_bWindowsDeviceChanged = SDL_TRUE; /* force a scan of the system for joysticks this first time */
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
WINDOWS_JoystickDetect();
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2021-08-03 09:02:32 +00:00
|
|
|
#ifndef __WINRT__
|
2021-07-24 06:45:18 +00:00
|
|
|
SDL_CreateDeviceNotificationFunc();
|
|
|
|
|
2020-12-13 06:11:00 +00:00
|
|
|
s_bJoystickThread = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_THREAD, SDL_FALSE);
|
2020-12-13 06:08:02 +00:00
|
|
|
if (s_bJoystickThread) {
|
|
|
|
if (SDL_StartJoystickThread() < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
2021-04-26 19:54:14 +00:00
|
|
|
#endif
|
2018-08-09 23:00:17 +00:00
|
|
|
return 0;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* return the number of joysticks that are connected right now */
|
2018-08-09 23:00:17 +00:00
|
|
|
static int
|
|
|
|
WINDOWS_JoystickGetCount(void)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
int nJoysticks = 0;
|
|
|
|
JoyStick_DeviceData *device = SYS_Joystick;
|
|
|
|
while (device) {
|
|
|
|
nJoysticks++;
|
|
|
|
device = device->pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nJoysticks;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* detect any new joysticks being inserted into the system */
|
2018-08-09 23:00:17 +00:00
|
|
|
static void
|
|
|
|
WINDOWS_JoystickDetect(void)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2020-12-18 21:10:36 +00:00
|
|
|
int device_index = 0;
|
2015-06-21 15:33:46 +00:00
|
|
|
JoyStick_DeviceData *pCurList = NULL;
|
|
|
|
|
|
|
|
/* only enum the devices if the joystick thread told us something changed */
|
2020-12-18 21:10:36 +00:00
|
|
|
if (!s_bWindowsDeviceChanged) {
|
2015-06-21 15:33:46 +00:00
|
|
|
return; /* thread hasn't signaled, nothing to do right now. */
|
|
|
|
}
|
|
|
|
|
2020-12-13 06:08:02 +00:00
|
|
|
if (s_mutexJoyStickEnum) {
|
|
|
|
SDL_LockMutex(s_mutexJoyStickEnum);
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2020-12-18 21:10:36 +00:00
|
|
|
s_bWindowsDeviceChanged = SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
pCurList = SYS_Joystick;
|
|
|
|
SYS_Joystick = NULL;
|
|
|
|
|
|
|
|
/* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
|
|
|
|
SDL_DINPUT_JoystickDetect(&pCurList);
|
|
|
|
|
|
|
|
/* Look for XInput devices. Do this last, so they're first in the final list. */
|
|
|
|
SDL_XINPUT_JoystickDetect(&pCurList);
|
|
|
|
|
2020-12-13 06:08:02 +00:00
|
|
|
if (s_mutexJoyStickEnum) {
|
|
|
|
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
while (pCurList) {
|
|
|
|
JoyStick_DeviceData *pListNext = NULL;
|
|
|
|
|
|
|
|
if (pCurList->bXInputDevice) {
|
2020-07-08 15:28:34 +00:00
|
|
|
#if SDL_HAPTIC_XINPUT
|
2021-05-25 09:33:23 +00:00
|
|
|
SDL_XINPUT_HapticMaybeRemoveDevice(pCurList->XInputUserId);
|
2020-07-08 15:28:34 +00:00
|
|
|
#endif
|
2015-06-21 15:33:46 +00:00
|
|
|
} else {
|
2020-07-08 15:28:34 +00:00
|
|
|
#if SDL_HAPTIC_DINPUT
|
2021-05-25 09:33:23 +00:00
|
|
|
SDL_DINPUT_HapticMaybeRemoveDevice(&pCurList->dxdevice);
|
2020-07-08 15:28:34 +00:00
|
|
|
#endif
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2016-08-26 19:18:08 +00:00
|
|
|
SDL_PrivateJoystickRemoved(pCurList->nInstanceID);
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
pListNext = pCurList->pNext;
|
|
|
|
SDL_free(pCurList->joystickname);
|
|
|
|
SDL_free(pCurList);
|
|
|
|
pCurList = pListNext;
|
|
|
|
}
|
|
|
|
|
2020-12-18 21:10:36 +00:00
|
|
|
for (device_index = 0, pCurList = SYS_Joystick; pCurList; ++device_index, pCurList = pCurList->pNext) {
|
|
|
|
if (pCurList->send_add_event) {
|
|
|
|
if (pCurList->bXInputDevice) {
|
2020-07-08 15:28:34 +00:00
|
|
|
#if SDL_HAPTIC_XINPUT
|
2021-05-25 09:33:23 +00:00
|
|
|
SDL_XINPUT_HapticMaybeAddDevice(pCurList->XInputUserId);
|
2020-07-08 15:28:34 +00:00
|
|
|
#endif
|
2020-12-18 21:10:36 +00:00
|
|
|
} else {
|
2020-07-08 15:28:34 +00:00
|
|
|
#if SDL_HAPTIC_DINPUT
|
2021-05-25 09:33:23 +00:00
|
|
|
SDL_DINPUT_HapticMaybeAddDevice(&pCurList->dxdevice);
|
2020-07-08 15:28:34 +00:00
|
|
|
#endif
|
2020-12-18 21:10:36 +00:00
|
|
|
}
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2020-12-18 21:10:36 +00:00
|
|
|
SDL_PrivateJoystickAdded(pCurList->nInstanceID);
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2020-12-18 21:10:36 +00:00
|
|
|
pCurList->send_add_event = SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function to get the device-dependent name of a joystick */
|
2018-08-09 23:00:17 +00:00
|
|
|
static const char *
|
|
|
|
WINDOWS_JoystickGetDeviceName(int device_index)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
JoyStick_DeviceData *device = SYS_Joystick;
|
2020-05-29 21:48:05 +00:00
|
|
|
int index;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2020-05-29 21:48:05 +00:00
|
|
|
for (index = device_index; index > 0; index--)
|
2015-06-21 15:33:46 +00:00
|
|
|
device = device->pNext;
|
|
|
|
|
|
|
|
return device->joystickname;
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:53:14 +00:00
|
|
|
static int
|
|
|
|
WINDOWS_JoystickGetDevicePlayerIndex(int device_index)
|
|
|
|
{
|
|
|
|
JoyStick_DeviceData *device = SYS_Joystick;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = device_index; index > 0; index--)
|
|
|
|
device = device->pNext;
|
|
|
|
|
|
|
|
return device->bXInputDevice ? (int)device->XInputUserId : -1;
|
|
|
|
}
|
|
|
|
|
2019-12-21 04:12:03 +00:00
|
|
|
static void
|
|
|
|
WINDOWS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
/* return the stable device guid for this device index */
|
|
|
|
static SDL_JoystickGUID
|
|
|
|
WINDOWS_JoystickGetDeviceGUID(int device_index)
|
|
|
|
{
|
|
|
|
JoyStick_DeviceData *device = SYS_Joystick;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = device_index; index > 0; index--)
|
|
|
|
device = device->pNext;
|
|
|
|
|
|
|
|
return device->guid;
|
|
|
|
}
|
|
|
|
|
2015-06-21 15:33:46 +00:00
|
|
|
/* Function to perform the mapping between current device instance and this joysticks instance id */
|
2018-08-09 23:00:17 +00:00
|
|
|
static SDL_JoystickID
|
|
|
|
WINDOWS_JoystickGetDeviceInstanceID(int device_index)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
JoyStick_DeviceData *device = SYS_Joystick;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = device_index; index > 0; index--)
|
|
|
|
device = device->pNext;
|
|
|
|
|
|
|
|
return device->nInstanceID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function to open a joystick for use.
|
|
|
|
The joystick to open is specified by the device index.
|
|
|
|
This should fill the nbuttons and naxes fields of the joystick structure.
|
|
|
|
It returns 0, or -1 if there is an error.
|
|
|
|
*/
|
2018-08-09 23:00:17 +00:00
|
|
|
static int
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2020-05-29 21:48:05 +00:00
|
|
|
JoyStick_DeviceData *device = SYS_Joystick;
|
|
|
|
int index;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2020-05-29 21:48:05 +00:00
|
|
|
for (index = device_index; index > 0; index--)
|
|
|
|
device = device->pNext;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
/* allocate memory for system specific hardware data */
|
2020-05-29 21:48:05 +00:00
|
|
|
joystick->instance_id = device->nInstanceID;
|
2015-06-21 15:33:46 +00:00
|
|
|
joystick->hwdata =
|
|
|
|
(struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
|
|
|
|
if (joystick->hwdata == NULL) {
|
|
|
|
return SDL_OutOfMemory();
|
|
|
|
}
|
|
|
|
SDL_zerop(joystick->hwdata);
|
2020-05-29 21:48:05 +00:00
|
|
|
joystick->hwdata->guid = device->guid;
|
2015-06-21 15:33:46 +00:00
|
|
|
|
2020-05-29 21:48:05 +00:00
|
|
|
if (device->bXInputDevice) {
|
|
|
|
return SDL_XINPUT_JoystickOpen(joystick, device);
|
2015-06-21 15:33:46 +00:00
|
|
|
} else {
|
2020-05-29 21:48:05 +00:00
|
|
|
return SDL_DINPUT_JoystickOpen(joystick, device);
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
static int
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
2018-08-09 23:00:17 +00:00
|
|
|
{
|
|
|
|
if (joystick->hwdata->bXInputDevice) {
|
2020-02-04 20:48:53 +00:00
|
|
|
return SDL_XINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble);
|
2018-08-09 23:00:17 +00:00
|
|
|
} else {
|
2020-02-04 20:48:53 +00:00
|
|
|
return SDL_DINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble);
|
2018-08-09 23:00:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 02:57:37 +00:00
|
|
|
static int
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
2020-11-12 02:57:37 +00:00
|
|
|
{
|
|
|
|
return SDL_Unsupported();
|
|
|
|
}
|
|
|
|
|
2020-11-05 19:07:54 +00:00
|
|
|
static SDL_bool
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickHasLED(SDL_Joystick *joystick)
|
2020-11-05 19:07:54 +00:00
|
|
|
{
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
2020-04-30 15:57:29 +00:00
|
|
|
static int
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
|
|
|
|
{
|
|
|
|
return SDL_Unsupported();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
WINDOWS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
|
2020-04-30 15:57:29 +00:00
|
|
|
{
|
|
|
|
return SDL_Unsupported();
|
|
|
|
}
|
|
|
|
|
2020-11-17 18:30:20 +00:00
|
|
|
static int
|
|
|
|
WINDOWS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
|
|
|
|
{
|
|
|
|
return SDL_Unsupported();
|
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
static void
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickUpdate(SDL_Joystick *joystick)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2018-08-09 23:03:50 +00:00
|
|
|
if (!joystick->hwdata) {
|
2015-06-21 15:33:46 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (joystick->hwdata->bXInputDevice) {
|
|
|
|
SDL_XINPUT_JoystickUpdate(joystick);
|
|
|
|
} else {
|
|
|
|
SDL_DINPUT_JoystickUpdate(joystick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function to close a joystick after use */
|
2018-08-09 23:00:17 +00:00
|
|
|
static void
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickClose(SDL_Joystick *joystick)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
if (joystick->hwdata->bXInputDevice) {
|
|
|
|
SDL_XINPUT_JoystickClose(joystick);
|
|
|
|
} else {
|
|
|
|
SDL_DINPUT_JoystickClose(joystick);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_free(joystick->hwdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Function to perform any system-specific joystick related cleanup */
|
2018-08-09 23:00:17 +00:00
|
|
|
static void
|
|
|
|
WINDOWS_JoystickQuit(void)
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
|
|
|
JoyStick_DeviceData *device = SYS_Joystick;
|
|
|
|
|
|
|
|
while (device) {
|
|
|
|
JoyStick_DeviceData *device_next = device->pNext;
|
|
|
|
SDL_free(device->joystickname);
|
|
|
|
SDL_free(device);
|
|
|
|
device = device_next;
|
|
|
|
}
|
|
|
|
SYS_Joystick = NULL;
|
|
|
|
|
2021-07-24 06:45:18 +00:00
|
|
|
#ifndef __WINRT__
|
2020-12-13 06:08:02 +00:00
|
|
|
if (s_bJoystickThread) {
|
|
|
|
SDL_StopJoystickThread();
|
|
|
|
} else {
|
|
|
|
SDL_CleanupDeviceNotification(&s_notification_data);
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
2021-07-24 06:45:18 +00:00
|
|
|
|
|
|
|
SDL_CleanupDeviceNotificationFunc();
|
2021-08-03 09:02:32 +00:00
|
|
|
#endif
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
SDL_DINPUT_JoystickQuit();
|
|
|
|
SDL_XINPUT_JoystickQuit();
|
2016-10-07 23:32:58 +00:00
|
|
|
|
2020-12-18 21:10:36 +00:00
|
|
|
s_bWindowsDeviceChanged = SDL_FALSE;
|
2015-06-21 15:33:46 +00:00
|
|
|
}
|
|
|
|
|
2020-05-29 20:37:21 +00:00
|
|
|
static SDL_bool
|
|
|
|
WINDOWS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
|
|
|
{
|
|
|
|
return SDL_FALSE;
|
|
|
|
}
|
|
|
|
|
2018-08-09 23:00:17 +00:00
|
|
|
SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
|
2015-06-21 15:33:46 +00:00
|
|
|
{
|
2018-08-09 23:00:17 +00:00
|
|
|
WINDOWS_JoystickInit,
|
|
|
|
WINDOWS_JoystickGetCount,
|
|
|
|
WINDOWS_JoystickDetect,
|
|
|
|
WINDOWS_JoystickGetDeviceName,
|
2018-10-25 23:53:14 +00:00
|
|
|
WINDOWS_JoystickGetDevicePlayerIndex,
|
2019-12-21 04:12:03 +00:00
|
|
|
WINDOWS_JoystickSetDevicePlayerIndex,
|
2018-08-09 23:00:17 +00:00
|
|
|
WINDOWS_JoystickGetDeviceGUID,
|
|
|
|
WINDOWS_JoystickGetDeviceInstanceID,
|
|
|
|
WINDOWS_JoystickOpen,
|
|
|
|
WINDOWS_JoystickRumble,
|
2020-11-12 02:57:37 +00:00
|
|
|
WINDOWS_JoystickRumbleTriggers,
|
2020-11-05 19:07:54 +00:00
|
|
|
WINDOWS_JoystickHasLED,
|
2020-04-30 15:57:29 +00:00
|
|
|
WINDOWS_JoystickSetLED,
|
2021-07-08 20:22:41 +00:00
|
|
|
WINDOWS_JoystickSendEffect,
|
2020-11-17 18:30:20 +00:00
|
|
|
WINDOWS_JoystickSetSensorsEnabled,
|
2018-08-09 23:00:17 +00:00
|
|
|
WINDOWS_JoystickUpdate,
|
|
|
|
WINDOWS_JoystickClose,
|
|
|
|
WINDOWS_JoystickQuit,
|
2020-05-29 20:37:21 +00:00
|
|
|
WINDOWS_JoystickGetGamepadMapping
|
2018-08-09 23:00:17 +00:00
|
|
|
};
|
2015-06-21 15:33:46 +00:00
|
|
|
|
|
|
|
#endif /* SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT */
|
|
|
|
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|