LIBS: updated sdl2
parent
15de72dd3b
commit
db23192daf
|
@ -100,6 +100,10 @@
|
|||
#cmakedefine HAVE_WCSSTR 1
|
||||
#cmakedefine HAVE_WCSCMP 1
|
||||
#cmakedefine HAVE_WCSNCMP 1
|
||||
#cmakedefine HAVE_WCSCASECMP 1
|
||||
#cmakedefine HAVE__WCSICMP 1
|
||||
#cmakedefine HAVE_WCSNCASECMP 1
|
||||
#cmakedefine HAVE__WCSNICMP 1
|
||||
#cmakedefine HAVE_STRLEN 1
|
||||
#cmakedefine HAVE_STRLCPY 1
|
||||
#cmakedefine HAVE_STRLCAT 1
|
||||
|
|
|
@ -103,6 +103,10 @@
|
|||
#undef HAVE_WCSSTR
|
||||
#undef HAVE_WCSCMP
|
||||
#undef HAVE_WCSNCMP
|
||||
#undef HAVE_WCSCASECMP
|
||||
#undef HAVE__WCSICMP
|
||||
#undef HAVE_WCSNCASECMP
|
||||
#undef HAVE__WCSNICMP
|
||||
#undef HAVE_STRLEN
|
||||
#undef HAVE_STRLCPY
|
||||
#undef HAVE_STRLCAT
|
||||
|
|
|
@ -198,11 +198,6 @@
|
|||
/* enable iOS extended launch screen */
|
||||
#define SDL_IPHONE_LAUNCHSCREEN 1
|
||||
|
||||
/* Set max recognized G-force from accelerometer
|
||||
See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed
|
||||
*/
|
||||
#define SDL_IPHONE_MAX_GFORCE 5.0
|
||||
|
||||
/* enable filesystem support */
|
||||
#define SDL_FILESYSTEM_COCOA 1
|
||||
|
||||
|
|
|
@ -103,6 +103,8 @@
|
|||
#define HAVE_WCSLCPY 1
|
||||
#define HAVE_WCSLCAT 1
|
||||
#define HAVE_WCSCMP 1
|
||||
#define HAVE__WCSICMP 1
|
||||
#define HAVE__WCSNICMP 1
|
||||
#define HAVE_STRLEN 1
|
||||
#define HAVE_STRLCPY 1
|
||||
#define HAVE_STRLCAT 1
|
||||
|
|
|
@ -134,6 +134,8 @@ typedef unsigned int uintptr_t;
|
|||
#define HAVE_STRNCMP 1
|
||||
#define HAVE__STRICMP 1
|
||||
#define HAVE__STRNICMP 1
|
||||
#define HAVE__WCSICMP 1
|
||||
#define HAVE__WCSNICMP 1
|
||||
#define HAVE_ACOS 1
|
||||
#define HAVE_ACOSF 1
|
||||
#define HAVE_ASIN 1
|
||||
|
@ -189,6 +191,20 @@ typedef unsigned int uintptr_t;
|
|||
#define HAVE_STDDEF_H 1
|
||||
#endif
|
||||
|
||||
/* Check to see if we have Windows 10 build environment */
|
||||
#if _MSC_VER >= 1911 /* Visual Studio 15.3 */
|
||||
#include <sdkddkver.h>
|
||||
#if _WIN32_WINNT >= 0x0601 /* Windows 7 */
|
||||
#define SDL_WINDOWS7_SDK
|
||||
#endif
|
||||
#if _WIN32_WINNT >= 0x0602 /* Windows 8 */
|
||||
#define SDL_WINDOWS8_SDK
|
||||
#endif
|
||||
#if _WIN32_WINNT >= 0x0A00 /* Windows 10 */
|
||||
#define SDL_WINDOWS10_SDK
|
||||
#endif
|
||||
#endif /* _MSC_VER >= 1911 */
|
||||
|
||||
/* Enable various audio drivers */
|
||||
#define SDL_AUDIO_DRIVER_WASAPI 1
|
||||
#define SDL_AUDIO_DRIVER_DSOUND 1
|
||||
|
@ -199,10 +215,12 @@ typedef unsigned int uintptr_t;
|
|||
/* Enable various input drivers */
|
||||
#define SDL_JOYSTICK_DINPUT 1
|
||||
#define SDL_JOYSTICK_HIDAPI 1
|
||||
#ifndef __WINRT__
|
||||
#define SDL_JOYSTICK_RAWINPUT 1
|
||||
#endif
|
||||
#define SDL_JOYSTICK_VIRTUAL 1
|
||||
#if _MSC_VER >= 1911
|
||||
#define SDL_JOYSTICK_WGI 1 /* This requires Windows SDK 10.0.16299.0 or newer */
|
||||
#ifdef SDL_WINDOWS10_SDK
|
||||
#define SDL_JOYSTICK_WGI 1
|
||||
#endif
|
||||
#define SDL_JOYSTICK_XINPUT 1
|
||||
#define SDL_HAPTIC_DINPUT 1
|
||||
|
@ -227,7 +245,7 @@ typedef unsigned int uintptr_t;
|
|||
#ifndef SDL_VIDEO_RENDER_D3D
|
||||
#define SDL_VIDEO_RENDER_D3D 1
|
||||
#endif
|
||||
#if _MSC_VER >= 1911
|
||||
#ifdef SDL_WINDOWS7_SDK
|
||||
#define SDL_VIDEO_RENDER_D3D11 1
|
||||
#endif
|
||||
|
||||
|
|
|
@ -105,6 +105,11 @@ typedef enum
|
|||
SDL_JOYSTICK_POWER_MAX
|
||||
} SDL_JoystickPowerLevel;
|
||||
|
||||
/* Set max recognized G-force from accelerometer
|
||||
See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed
|
||||
*/
|
||||
#define SDL_IPHONE_MAX_GFORCE 5.0
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
|
|
|
@ -469,6 +469,8 @@ extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar
|
|||
|
||||
extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2);
|
||||
extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen);
|
||||
extern DECLSPEC int SDLCALL SDL_wcscasecmp(const wchar_t *str1, const wchar_t *str2);
|
||||
extern DECLSPEC int SDLCALL SDL_wcsncasecmp(const wchar_t *str1, const wchar_t *str2, size_t len);
|
||||
|
||||
extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str);
|
||||
extern DECLSPEC size_t SDLCALL SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen);
|
||||
|
|
|
@ -786,3 +786,5 @@
|
|||
#define SDL_GameControllerSetSensorEnabled SDL_GameControllerSetSensorEnabled_REAL
|
||||
#define SDL_GameControllerIsSensorEnabled SDL_GameControllerIsSensorEnabled_REAL
|
||||
#define SDL_GameControllerGetSensorData SDL_GameControllerGetSensorData_REAL
|
||||
#define SDL_wcscasecmp SDL_wcscasecmp_REAL
|
||||
#define SDL_wcsncasecmp SDL_wcsncasecmp_REAL
|
||||
|
|
|
@ -847,3 +847,5 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_GameControllerHasSensor,(SDL_GameController *a, SDL
|
|||
SDL_DYNAPI_PROC(int,SDL_GameControllerSetSensorEnabled,(SDL_GameController *a, SDL_SensorType b, SDL_bool c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_GameControllerIsSensorEnabled,(SDL_GameController *a, SDL_SensorType b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GameControllerGetSensorData,(SDL_GameController *a, SDL_SensorType b, float *c, int d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_wcscasecmp,(const wchar_t *a, const wchar_t *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_wcsncasecmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
|
||||
|
|
|
@ -48,7 +48,12 @@ SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType)
|
|||
{
|
||||
static wstring path;
|
||||
if (path.empty()) {
|
||||
path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data();
|
||||
/* Windows 1903 supports mods, via the EffectiveLocation API */
|
||||
if (Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8, 0)) {
|
||||
path = Windows::ApplicationModel::Package::Current->EffectiveLocation->Path->Data();
|
||||
} else {
|
||||
path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data();
|
||||
}
|
||||
}
|
||||
return path.c_str();
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#define make_path PLATFORM_make_path
|
||||
#define read_thread PLATFORM_read_thread
|
||||
|
||||
#undef HIDAPI_H__
|
||||
#if __LINUX__
|
||||
|
||||
#include "../../core/linux/SDL_udev.h"
|
||||
|
@ -130,7 +131,7 @@ static const SDL_UDEV_Symbols *udev_ctx = NULL;
|
|||
#undef read_thread
|
||||
|
||||
#ifdef HAVE_HIDAPI_NVAGIPMAN
|
||||
#define HAVE_DRIVER_BACKEND
|
||||
#define HAVE_DRIVER_BACKEND 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
|
@ -160,6 +161,7 @@ static const SDL_UDEV_Symbols *udev_ctx = NULL;
|
|||
#define hid_error DRIVER_hid_error
|
||||
|
||||
#ifdef HAVE_HIDAPI_NVAGIPMAN
|
||||
#undef HIDAPI_H__
|
||||
#include "nvagipman/hid.c"
|
||||
#else
|
||||
#error Need a driver hid.c for this platform!
|
||||
|
@ -496,6 +498,28 @@ LIBUSB_CopyHIDDeviceInfo(struct LIBUSB_hid_device_info *pSrc,
|
|||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#if HAVE_DRIVER_BACKEND
|
||||
static void
|
||||
DRIVER_CopyHIDDeviceInfo(struct DRIVER_hid_device_info *pSrc,
|
||||
struct hid_device_info *pDst)
|
||||
{
|
||||
COPY_IF_EXISTS(path)
|
||||
pDst->vendor_id = pSrc->vendor_id;
|
||||
pDst->product_id = pSrc->product_id;
|
||||
WCOPY_IF_EXISTS(serial_number)
|
||||
pDst->release_number = pSrc->release_number;
|
||||
WCOPY_IF_EXISTS(manufacturer_string)
|
||||
WCOPY_IF_EXISTS(product_string)
|
||||
pDst->usage_page = pSrc->usage_page;
|
||||
pDst->usage = pSrc->usage;
|
||||
pDst->interface_number = pSrc->interface_number;
|
||||
pDst->interface_class = pSrc->interface_class;
|
||||
pDst->interface_subclass = pSrc->interface_subclass;
|
||||
pDst->interface_protocol = pSrc->interface_protocol;
|
||||
pDst->next = NULL;
|
||||
}
|
||||
#endif /* HAVE_DRIVER_BACKEND */
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
static void
|
||||
PLATFORM_CopyHIDDeviceInfo(struct PLATFORM_hid_device_info *pSrc,
|
||||
|
@ -647,6 +671,21 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
driver_devs = DRIVER_hid_enumerate(vendor_id, product_id);
|
||||
for (driver_dev = driver_devs; driver_dev; driver_dev = driver_dev->next) {
|
||||
new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
|
||||
DRIVER_CopyHIDDeviceInfo(driver_dev, new_dev);
|
||||
|
||||
if (last != NULL) {
|
||||
last->next = new_dev;
|
||||
} else {
|
||||
devs = new_dev;
|
||||
}
|
||||
last = new_dev;
|
||||
}
|
||||
#endif /* HAVE_DRIVER_BACKEND */
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
if (udev_ctx) {
|
||||
raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
|
||||
|
@ -661,6 +700,16 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
for (driver_dev = driver_devs; driver_dev; driver_dev = driver_dev->next) {
|
||||
if (raw_dev->vendor_id == driver_dev->vendor_id &&
|
||||
raw_dev->product_id == driver_dev->product_id &&
|
||||
(raw_dev->interface_number < 0 || raw_dev->interface_number == driver_dev->interface_number)) {
|
||||
bFound = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!bFound) {
|
||||
new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
|
||||
|
@ -755,8 +804,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bEx
|
|||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
#if HAVE_DRIVER_BACKEND
|
||||
if (udev_ctx &&
|
||||
(pDevice = (hid_device*) DRIVER_hid_open_path(path, bExclusive)) != NULL) {
|
||||
if ((pDevice = (hid_device*) DRIVER_hid_open_path(path, bExclusive)) != NULL) {
|
||||
|
||||
HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &DRIVER_Backend);
|
||||
return WrapHIDDevice(wrapper);
|
||||
|
|
|
@ -616,7 +616,7 @@ static ControllerMapping_t *SDL_CreateMappingForRAWINPUTController(SDL_JoystickG
|
|||
char mapping_string[1024];
|
||||
|
||||
SDL_strlcpy(mapping_string, "none,*,", sizeof(mapping_string));
|
||||
SDL_strlcat(mapping_string, "a:b0,b:b1,x:b2,y:b3,back:b6,guide:b10,start:b7,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a1,lefty:a0,rightx:a3,righty:a2,lefttrigger:a4,righttrigger:a5,", sizeof(mapping_string));
|
||||
SDL_strlcat(mapping_string, "a:b0,b:b1,x:b2,y:b3,back:b6,guide:b10,start:b7,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", sizeof(mapping_string));
|
||||
|
||||
return SDL_PrivateAddMappingForGUID(guid, mapping_string,
|
||||
&existing, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT);
|
||||
|
|
|
@ -1036,6 +1036,7 @@ SDL_JoystickClose(SDL_Joystick *joystick)
|
|||
SDL_free(touchpad->fingers);
|
||||
}
|
||||
SDL_free(joystick->touchpads);
|
||||
SDL_free(joystick->sensors);
|
||||
SDL_free(joystick);
|
||||
|
||||
SDL_UnlockJoysticks();
|
||||
|
@ -1638,6 +1639,7 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c
|
|||
} replacements[] = {
|
||||
{ "NVIDIA Corporation ", "" },
|
||||
{ "Performance Designed Products", "PDP" },
|
||||
{ "HORI CO.,LTD.", "HORI" },
|
||||
{ "HORI CO.,LTD", "HORI" },
|
||||
};
|
||||
const char *custom_name;
|
||||
|
@ -1727,6 +1729,12 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c
|
|||
return name;
|
||||
}
|
||||
|
||||
SDL_GameControllerType
|
||||
SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product)
|
||||
{
|
||||
return SDL_GetJoystickGameControllerType(NULL, vendor, product, -1, 0, 0, 0);
|
||||
}
|
||||
|
||||
SDL_GameControllerType
|
||||
SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name)
|
||||
{
|
||||
|
|
|
@ -58,6 +58,7 @@ extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint1
|
|||
extern char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name);
|
||||
|
||||
/* Function to return the type of a controller */
|
||||
extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product);
|
||||
extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name);
|
||||
extern SDL_GameControllerType SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
|
||||
|
||||
|
|
|
@ -526,11 +526,15 @@ GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
|||
static SDL_bool
|
||||
JoystickAlreadyKnown(IOHIDDeviceRef ioHIDDeviceObject)
|
||||
{
|
||||
recDevice *i;
|
||||
|
||||
#if defined(SDL_JOYSTICK_MFI)
|
||||
extern SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device);
|
||||
if (IOS_SupportedHIDDevice(ioHIDDeviceObject)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
recDevice *i;
|
||||
#endif
|
||||
|
||||
for (i = gpDeviceList; i != NULL; i = i->pNext) {
|
||||
if (i->deviceRef == ioHIDDeviceObject) {
|
||||
return SDL_TRUE;
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_XBOX360
|
||||
|
||||
/* Define this if you want to log all packets from the controller */
|
||||
/*#define DEBUG_XBOX_PROTOCOL*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
Uint8 last_state[USB_PACKET_LENGTH];
|
||||
} SDL_DriverXbox360_Context;
|
||||
|
@ -77,6 +81,7 @@ HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType
|
|||
/* This is the Steam Virtual Gamepad, which isn't supported by this driver */
|
||||
return SDL_FALSE;
|
||||
}
|
||||
#endif
|
||||
#if defined(__MACOSX__)
|
||||
/* Wired Xbox One controllers are handled by this driver, interfacing with
|
||||
the 360Controller driver available from:
|
||||
|
@ -87,7 +92,6 @@ HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType
|
|||
if (IsBluetoothXboxOneController(vendor_id, product_id)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
#endif
|
||||
return (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE;
|
||||
#else
|
||||
return (type == SDL_CONTROLLER_TYPE_XBOX360) ? SDL_TRUE : SDL_FALSE;
|
||||
|
@ -126,6 +130,9 @@ HIDAPI_DriverXbox360_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystic
|
|||
static void
|
||||
HIDAPI_DriverXbox360_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
|
||||
{
|
||||
if (!device->dev) {
|
||||
return;
|
||||
}
|
||||
SetSlotLED(device->dev, (player_index % 4));
|
||||
}
|
||||
|
||||
|
@ -296,7 +303,12 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
}
|
||||
|
||||
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, ctx, data, size);
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
HIDAPI_DumpPacket("Xbox 360 packet: size = %d", data, size);
|
||||
#endif
|
||||
if (data[0] == 0x00) {
|
||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, ctx, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_XBOX360
|
||||
|
||||
/* Define this if you want to log all packets from the controller */
|
||||
/*#define DEBUG_XBOX_PROTOCOL*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
SDL_bool connected;
|
||||
|
@ -125,6 +128,9 @@ HIDAPI_DriverXbox360W_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joysti
|
|||
static void
|
||||
HIDAPI_DriverXbox360W_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
|
||||
{
|
||||
if (!device->dev) {
|
||||
return;
|
||||
}
|
||||
SetSlotLED(device->dev, (player_index % 4));
|
||||
}
|
||||
|
||||
|
@ -244,6 +250,9 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
}
|
||||
|
||||
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
HIDAPI_DumpPacket("Xbox 360 wireless packet: size = %d", data, size);
|
||||
#endif
|
||||
if (size == 2 && data[0] == 0x08) {
|
||||
SDL_bool connected = (data[1] & 0x80) ? SDL_TRUE : SDL_FALSE;
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
|
|
|
@ -34,14 +34,15 @@
|
|||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
|
||||
|
||||
/* Define this if you want verbose logging of the init sequence */
|
||||
/*#define DEBUG_JOYSTICK*/
|
||||
|
||||
/* Define this if you want to log all packets from the controller */
|
||||
/*#define DEBUG_XBOX_PROTOCOL*/
|
||||
|
||||
/* The amount of time to wait after hotplug to send controller init sequence */
|
||||
#define CONTROLLER_INIT_DELAY_MS 1500 /* 475 for Xbox One S, 1275 for the PDP Battlefield 1 */
|
||||
#define CONTROLLER_NEGOTIATION_TIMEOUT_MS 300
|
||||
#define CONTROLLER_PREPARE_INPUT_TIMEOUT_MS 50
|
||||
|
||||
/* The amount of time to wait after init for valid input */
|
||||
#define CONTROLLER_INPUT_DELAY_MS 50 /* 42 for Razer Wolverine Ultimate */
|
||||
|
||||
/* Connect controller */
|
||||
static const Uint8 xboxone_init0[] = {
|
||||
|
@ -71,13 +72,6 @@ static const Uint8 xboxone_init5[] = {
|
|||
0x00, 0x00, 0xFF, 0x00, 0xEB
|
||||
};
|
||||
|
||||
#ifdef REQUEST_SERIAL_NUMBER
|
||||
/* Request serial number */
|
||||
static const Uint8 xboxone_init_serial[] = {
|
||||
0x1E, 0x30, 0x07, 0x01, 0x04
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This specifies the selection of init packets that a gamepad
|
||||
* will be sent on init *and* the order in which they will be
|
||||
|
@ -106,28 +100,31 @@ static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
|
|||
*/
|
||||
{ 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init4, sizeof(xboxone_init4), { 0x00, 0x00 } },
|
||||
{ 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init5, sizeof(xboxone_init5), { 0x00, 0x00 } },
|
||||
|
||||
#ifdef REQUEST_SERIAL_NUMBER
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init_serial, sizeof(xboxone_init_serial), { 0x00, 0x00 } },
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN,
|
||||
XBOX_ONE_WIRELESS_PROTOCOL_V1,
|
||||
XBOX_ONE_WIRELESS_PROTOCOL_V2,
|
||||
XBOX_ONE_WIRELESS_PROTOCOL_V2
|
||||
} SDL_XboxOneWirelessProtocol;
|
||||
|
||||
typedef enum {
|
||||
XBOX_ONE_INIT_STATE_START_NEGOTIATING = 0,
|
||||
XBOX_ONE_INIT_STATE_NEGOTIATING = 1,
|
||||
XBOX_ONE_INIT_STATE_PREPARE_INPUT = 2,
|
||||
XBOX_ONE_INIT_STATE_COMPLETE = 3
|
||||
} SDL_XboxOneInitState;
|
||||
|
||||
typedef struct {
|
||||
Uint16 vendor_id;
|
||||
Uint16 product_id;
|
||||
SDL_bool bluetooth;
|
||||
SDL_XboxOneWirelessProtocol wireless_protocol;
|
||||
SDL_bool initialized;
|
||||
SDL_bool input_ready;
|
||||
SDL_XboxOneInitState init_state;
|
||||
int init_packet;
|
||||
Uint32 start_time;
|
||||
Uint32 initialized_time;
|
||||
Uint8 sequence;
|
||||
Uint32 send_time;
|
||||
Uint8 last_state[USB_PACKET_LENGTH];
|
||||
SDL_bool has_paddles;
|
||||
SDL_bool has_trigger_rumble;
|
||||
|
@ -146,7 +143,8 @@ IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
|
|||
if (vendor_id == USB_VENDOR_MICROSOFT) {
|
||||
if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
|
||||
product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
|
||||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH) {
|
||||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH ||
|
||||
product_id == USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -171,30 +169,21 @@ ControllerHasShareButton(Uint16 vendor_id, Uint16 product_id)
|
|||
return SDL_IsJoystickXboxOneSeriesX(vendor_id, product_id);
|
||||
}
|
||||
|
||||
/* Return true if this controller sends the 0x02 "waiting for init" packet */
|
||||
static SDL_bool
|
||||
ControllerSendsWaitingForInit(Uint16 vendor_id, Uint16 product_id)
|
||||
static void
|
||||
SetInitState(SDL_DriverXboxOne_Context *ctx, SDL_XboxOneInitState state)
|
||||
{
|
||||
if (vendor_id == USB_VENDOR_HYPERKIN) {
|
||||
/* The Hyperkin controllers always send 0x02 when waiting for init,
|
||||
and the Hyperkin Duke plays an Xbox startup animation, so we want
|
||||
to make sure we don't send the init sequence if it isn't needed.
|
||||
*/
|
||||
return SDL_TRUE;
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_PDP) {
|
||||
/* The PDP Rock Candy (PID 0x0246) doesn't send 0x02 on Linux for some reason */
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* It doesn't hurt to reinit, especially if a driver has misconfigured the controller */
|
||||
/*return SDL_TRUE;*/
|
||||
return SDL_FALSE;
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Setting init state %d\n", state);
|
||||
#endif
|
||||
ctx->init_state = state;
|
||||
}
|
||||
|
||||
static void
|
||||
SendAckIfNeeded(SDL_HIDAPI_Device *device, Uint8 *data, int size)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
/* The Windows driver is taking care of acks */
|
||||
#else
|
||||
if ((data[1] & 0x30) == 0x30) {
|
||||
Uint8 ack_packet[] = { 0x01, 0x20, data[2], 0x09, 0x00, data[0], 0x20, data[3], 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
|
@ -208,6 +197,39 @@ SendAckIfNeeded(SDL_HIDAPI_Device *device, Uint8 *data, int size)
|
|||
#endif
|
||||
hid_write(device->dev, ack_packet, sizeof(ack_packet));
|
||||
}
|
||||
#endif /* __WIN32__ */
|
||||
}
|
||||
|
||||
#if 0
|
||||
static SDL_bool
|
||||
SendSerialRequest(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
|
||||
{
|
||||
Uint8 serial_packet[] = { 0x1E, 0x30, 0x07, 0x01, 0x04 };
|
||||
|
||||
ctx->send_time = SDL_GetTicks();
|
||||
|
||||
/* Request the serial number
|
||||
* Sending this should be done only after the negotiation is complete.
|
||||
* It will cancel the announce packet if sent before that, and will be
|
||||
* ignored if sent during the negotiation.
|
||||
*/
|
||||
if (SDL_HIDAPI_LockRumble() < 0 ||
|
||||
SDL_HIDAPI_SendRumbleAndUnlock(device, serial_packet, sizeof(serial_packet)) != sizeof(serial_packet)) {
|
||||
SDL_SetError("Couldn't send serial packet");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SDL_bool
|
||||
ControllerNeedsNegotiation(SDL_DriverXboxOne_Context *ctx)
|
||||
{
|
||||
if (ctx->vendor_id == USB_VENDOR_PDP && ctx->product_id == 0x0246) {
|
||||
/* The PDP Rock Candy (PID 0x0246) doesn't send the announce packet on Linux for some reason */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
|
@ -215,11 +237,10 @@ SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
|
|||
{
|
||||
Uint16 vendor_id = ctx->vendor_id;
|
||||
Uint16 product_id = ctx->product_id;
|
||||
int i;
|
||||
Uint8 init_packet[USB_PACKET_LENGTH];
|
||||
|
||||
for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
|
||||
const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
|
||||
for ( ; ctx->init_packet < SDL_arraysize(xboxone_init_packets); ++ctx->init_packet) {
|
||||
const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[ctx->init_packet];
|
||||
|
||||
if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
|
||||
continue;
|
||||
|
@ -244,35 +265,22 @@ SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
|
|||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
HIDAPI_DumpPacket("Xbox One sending INIT packet: size = %d", init_packet, packet->size);
|
||||
#endif
|
||||
if (hid_write(device->dev, init_packet, packet->size) != packet->size) {
|
||||
ctx->send_time = SDL_GetTicks();
|
||||
|
||||
if (SDL_HIDAPI_LockRumble() < 0 ||
|
||||
SDL_HIDAPI_SendRumbleAndUnlock(device, init_packet, packet->size) != packet->size) {
|
||||
SDL_SetError("Couldn't write Xbox One initialization packet");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (packet->response[0]) {
|
||||
const Uint32 RESPONSE_TIMEOUT_MS = 100;
|
||||
Uint32 start = SDL_GetTicks();
|
||||
SDL_bool got_response = SDL_FALSE;
|
||||
|
||||
while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
int size;
|
||||
|
||||
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
HIDAPI_DumpPacket("Xbox One INIT packet: size = %d", data, size);
|
||||
#endif
|
||||
if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
|
||||
got_response = SDL_TRUE;
|
||||
}
|
||||
SendAckIfNeeded(device, data, size);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
SDL_Log("Init sequence %d got response after %u ms: %s\n", i, (SDL_GetTicks() - start), got_response ? "TRUE" : "FALSE");
|
||||
#endif
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* All done with the negotiation, prepare for input! */
|
||||
SetInitState(ctx, XBOX_ONE_INIT_STATE_PREPARE_INPUT);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
|
@ -317,6 +325,9 @@ HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystic
|
|||
{
|
||||
}
|
||||
|
||||
static SDL_bool HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
|
||||
static void HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
|
@ -339,14 +350,23 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
|
|||
ctx->vendor_id = device->vendor_id;
|
||||
ctx->product_id = device->product_id;
|
||||
ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
|
||||
ctx->initialized = ctx->bluetooth ? SDL_TRUE : SDL_FALSE;
|
||||
ctx->start_time = SDL_GetTicks();
|
||||
ctx->input_ready = SDL_TRUE;
|
||||
ctx->sequence = 1;
|
||||
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
|
||||
ctx->has_trigger_rumble = ControllerHasTriggerRumble(ctx->vendor_id, ctx->product_id);
|
||||
ctx->has_share_button = ControllerHasShareButton(ctx->vendor_id, ctx->product_id);
|
||||
|
||||
/* Assume that the controller is correctly initialized when we start */
|
||||
if (ControllerNeedsNegotiation(ctx)) {
|
||||
ctx->init_state = XBOX_ONE_INIT_STATE_START_NEGOTIATING;
|
||||
} else {
|
||||
ctx->init_state = XBOX_ONE_INIT_STATE_COMPLETE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Controller version: %d (0x%.4x)\n", device->version, device->version);
|
||||
#endif
|
||||
|
||||
/* Initialize the joystick capabilities */
|
||||
joystick->nbuttons = 15;
|
||||
if (ctx->has_share_button) {
|
||||
|
@ -356,7 +376,10 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
|
|||
joystick->nbuttons += 4;
|
||||
}
|
||||
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
|
||||
if (!ctx->bluetooth) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
@ -367,7 +390,7 @@ HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device)
|
|||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
|
||||
|
||||
if (ctx->bluetooth) {
|
||||
Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
|
||||
Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xEB };
|
||||
|
||||
rumble_packet[2] = ctx->left_trigger_rumble;
|
||||
rumble_packet[3] = ctx->right_trigger_rumble;
|
||||
|
@ -378,7 +401,7 @@ HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device)
|
|||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
} else {
|
||||
Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
|
||||
Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xEB };
|
||||
|
||||
rumble_packet[6] = ctx->left_trigger_rumble;
|
||||
rumble_packet[7] = ctx->right_trigger_rumble;
|
||||
|
@ -833,33 +856,107 @@ HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, hid_devi
|
|||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
static void
|
||||
HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
|
||||
SDL_Joystick *joystick = NULL;
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
int size;
|
||||
Uint8 flags = data[1];
|
||||
SDL_bool on_usb = (((flags & 0x0C) >> 2) == 0);
|
||||
|
||||
if (device->num_joysticks > 0) {
|
||||
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
|
||||
}
|
||||
if (!joystick) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!ctx->initialized &&
|
||||
!ControllerSendsWaitingForInit(device->vendor_id, device->product_id)) {
|
||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
|
||||
if (!SendControllerInit(device, ctx)) {
|
||||
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
ctx->initialized = SDL_TRUE;
|
||||
ctx->initialized_time = SDL_GetTicks();
|
||||
ctx->input_ready = SDL_FALSE;
|
||||
if (on_usb) {
|
||||
/* Does this ever happen? */
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
|
||||
} else {
|
||||
switch ((flags & 0x03)) {
|
||||
case 0:
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
|
||||
break;
|
||||
case 1:
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
|
||||
break;
|
||||
default: /* 2, 3 */
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SET_SERIAL_AFTER_OPEN
|
||||
static void
|
||||
HIDAPI_DriverXboxOne_HandleSerialIDPacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
|
||||
{
|
||||
char serial[ 29 ];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 14; ++i) {
|
||||
SDL_uitoa( data[6 + i], &serial[i * 2], 16 );
|
||||
}
|
||||
serial[i * 2] = '\0';
|
||||
|
||||
if (!joystick->serial || SDL_strcmp(joystick->serial, serial) != 0) {
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Setting serial number to %s\n", serial);
|
||||
#endif
|
||||
joystick->serial = SDL_strdup(serial);
|
||||
}
|
||||
}
|
||||
#endif /* SET_SERIAL_AFTER_OPEN */
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_UpdateInitState(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
|
||||
{
|
||||
SDL_XboxOneInitState prev_state;
|
||||
do
|
||||
{
|
||||
prev_state = ctx->init_state;
|
||||
|
||||
switch (ctx->init_state) {
|
||||
case XBOX_ONE_INIT_STATE_START_NEGOTIATING:
|
||||
#ifdef __WIN32__
|
||||
/* The Windows driver is taking care of negotiation */
|
||||
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
|
||||
#else
|
||||
SetInitState(ctx, XBOX_ONE_INIT_STATE_NEGOTIATING);
|
||||
ctx->init_packet = 0;
|
||||
if (!SendControllerInit(device, ctx)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case XBOX_ONE_INIT_STATE_NEGOTIATING:
|
||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->send_time + CONTROLLER_NEGOTIATION_TIMEOUT_MS)) {
|
||||
/* We haven't heard anything, let's move on */
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Init sequence %d timed out after %u ms\n", ctx->init_packet, (SDL_GetTicks() - ctx->send_time));
|
||||
#endif
|
||||
++ctx->init_packet;
|
||||
if (!SendControllerInit(device, ctx)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XBOX_ONE_INIT_STATE_PREPARE_INPUT:
|
||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->send_time + CONTROLLER_PREPARE_INPUT_TIMEOUT_MS)) {
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Prepare input complete after %u ms\n", (SDL_GetTicks() - ctx->send_time));
|
||||
#endif
|
||||
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
|
||||
}
|
||||
break;
|
||||
case XBOX_ONE_INIT_STATE_COMPLETE:
|
||||
break;
|
||||
}
|
||||
|
||||
} while (ctx->init_state != prev_state);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
int size;
|
||||
|
||||
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
|
@ -881,6 +978,9 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
case 0x02:
|
||||
HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, device->dev, ctx, data, size);
|
||||
break;
|
||||
case 0x04:
|
||||
HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(joystick, device->dev, ctx, data, size);
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
|
||||
|
@ -913,21 +1013,16 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
is firmware version 5.5.2641.0, and product version 0x0505 = 1285
|
||||
then 8 bytes of unknown data
|
||||
*/
|
||||
if (!ctx->initialized) {
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Controller announce after %u ms\n", (SDL_GetTicks() - ctx->start_time));
|
||||
#endif
|
||||
if (!SendControllerInit(device, ctx)) {
|
||||
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
ctx->initialized = SDL_TRUE;
|
||||
ctx->initialized_time = SDL_GetTicks();
|
||||
ctx->input_ready = SDL_FALSE;
|
||||
}
|
||||
SetInitState(ctx, XBOX_ONE_INIT_STATE_START_NEGOTIATING);
|
||||
break;
|
||||
case 0x03:
|
||||
/* Controller heartbeat */
|
||||
if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
|
||||
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
|
||||
}
|
||||
break;
|
||||
case 0x04:
|
||||
/* Unknown chatty controller information, sent by both sides */
|
||||
|
@ -948,16 +1043,21 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
The controller sends that in response to this request:
|
||||
0x1E 0x30 0x07 0x01 0x04
|
||||
*/
|
||||
#ifdef SET_SERIAL_AFTER_OPEN
|
||||
if (size == 20 && data[3] == 0x10) {
|
||||
HIDAPI_DriverXboxOne_HandleSerialIDPacket(joystick, ctx, data, size);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x20:
|
||||
if (!ctx->input_ready) {
|
||||
if (!SDL_TICKS_PASSED(SDL_GetTicks(), ctx->initialized_time + CONTROLLER_INPUT_DELAY_MS)) {
|
||||
#ifdef DEBUG_XBOX_PROTOCOL
|
||||
SDL_Log("Spurious input at %ums\n", SDL_GetTicks() - ctx->initialized_time);
|
||||
if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
|
||||
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
|
||||
|
||||
/* Ignore the first input, it may be spurious */
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Controller ignoring spurious input\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
ctx->input_ready = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
||||
break;
|
||||
|
@ -967,10 +1067,25 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
SendAckIfNeeded(device, data, size);
|
||||
|
||||
if (ctx->init_state == XBOX_ONE_INIT_STATE_NEGOTIATING) {
|
||||
const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[ctx->init_packet];
|
||||
|
||||
if (size >= 4 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Init sequence %d got response after %u ms\n", ctx->init_packet, (SDL_GetTicks() - ctx->send_time));
|
||||
#endif
|
||||
++ctx->init_packet;
|
||||
SendControllerInit(device, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HIDAPI_DriverXboxOne_UpdateInitState(device, ctx);
|
||||
|
||||
if (size < 0) {
|
||||
/* Read error, device is disconnected */
|
||||
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
|
||||
|
@ -978,6 +1093,20 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
return (size >= 0);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
{
|
||||
SDL_Joystick *joystick = NULL;
|
||||
|
||||
if (device->num_joysticks > 0) {
|
||||
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
|
||||
}
|
||||
if (!joystick) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return HIDAPI_DriverXboxOne_UpdateJoystick(device, joystick);
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
|
|
|
@ -192,7 +192,7 @@ HIDAPI_InitializeDiscovery()
|
|||
#if defined(__WIN32__)
|
||||
SDL_HIDAPI_discovery.m_nThreadID = SDL_ThreadID();
|
||||
|
||||
SDL_memset(&SDL_HIDAPI_discovery.m_wndClass, 0x0, sizeof(SDL_HIDAPI_discovery.m_wndClass));
|
||||
SDL_zero(SDL_HIDAPI_discovery.m_wndClass);
|
||||
SDL_HIDAPI_discovery.m_wndClass.hInstance = GetModuleHandle(NULL);
|
||||
SDL_HIDAPI_discovery.m_wndClass.lpszClassName = "SDL_HIDAPI_DEVICE_DETECTION";
|
||||
SDL_HIDAPI_discovery.m_wndClass.lpfnWndProc = ControllerWndProc; /* This function is called by windows */
|
||||
|
@ -203,8 +203,8 @@ HIDAPI_InitializeDiscovery()
|
|||
|
||||
{
|
||||
DEV_BROADCAST_DEVICEINTERFACE_A devBroadcast;
|
||||
SDL_memset( &devBroadcast, 0x0, sizeof( devBroadcast ) );
|
||||
|
||||
SDL_zero(devBroadcast);
|
||||
devBroadcast.dbcc_size = sizeof( devBroadcast );
|
||||
devBroadcast.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
devBroadcast.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
|
||||
|
@ -750,6 +750,38 @@ HIDAPI_AddDevice(struct hid_device_info *info)
|
|||
char *serial_number = HIDAPI_ConvertString(info->serial_number);
|
||||
|
||||
device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string);
|
||||
if (SDL_strncmp(device->name, "0x", 2) == 0) {
|
||||
/* Couldn't find a controller name, try to give it one based on device type */
|
||||
const char *name = NULL;
|
||||
|
||||
switch (SDL_GetJoystickGameControllerType(NULL, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
|
||||
case SDL_CONTROLLER_TYPE_XBOX360:
|
||||
name = "Xbox 360 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_XBOXONE:
|
||||
name = "Xbox One Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_PS3:
|
||||
name = "PS3 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_PS4:
|
||||
name = "PS4 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_PS5:
|
||||
name = "PS5 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
|
||||
name = "Nintendo Switch Pro Controller";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (name) {
|
||||
SDL_free(device->name);
|
||||
device->name = SDL_strdup(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (manufacturer_string) {
|
||||
SDL_free(manufacturer_string);
|
||||
|
@ -856,6 +888,29 @@ HIDAPI_UpdateDeviceList(void)
|
|||
SDL_UnlockJoysticks();
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL_HIDAPI_Device *device)
|
||||
{
|
||||
if (vendor_id == device->vendor_id && product_id == device->product_id) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
if (vendor_id == USB_VENDOR_MICROSOFT) {
|
||||
/* If we're looking for the wireless XBox 360 controller, also look for the dongle */
|
||||
if (product_id == 0x02a1 && device->product_id == 0x0719) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* If we're looking for the raw input Xbox One controller, match it against any other Xbox One controller */
|
||||
if (vendor_id == USB_VENDOR_MICROSOFT &&
|
||||
product_id == USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER &&
|
||||
SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
|
||||
{
|
||||
|
@ -895,18 +950,14 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons
|
|||
SDL_LockJoysticks();
|
||||
device = SDL_HIDAPI_devices;
|
||||
while (device) {
|
||||
if (device->vendor_id == vendor_id && device->product_id == product_id && device->driver) {
|
||||
if (device->driver &&
|
||||
HIDAPI_IsEquivalentToDevice(vendor_id, product_id, device)) {
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
SDL_UnlockJoysticks();
|
||||
|
||||
/* If we're looking for the wireless XBox 360 controller, also look for the dongle */
|
||||
if (!result && vendor_id == USB_VENDOR_MICROSOFT && product_id == 0x02a1) {
|
||||
return HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, 0x0719, version, name);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log("HIDAPI_IsDevicePresent() returning %s for 0x%.4x / 0x%.4x\n", result ? "true" : "false", vendor_id, product_id);
|
||||
#endif
|
||||
|
|
|
@ -21,13 +21,6 @@
|
|||
#include "../../SDL_internal.h"
|
||||
|
||||
/* This is the iOS implementation of the SDL joystick API */
|
||||
#include "SDL_mfijoystick_c.h"
|
||||
|
||||
#if !TARGET_OS_OSX
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#include "../../../include/SDL_config_iphoneos.h"
|
||||
#endif
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_joystick.h"
|
||||
|
@ -37,6 +30,7 @@
|
|||
#include "../SDL_joystick_c.h"
|
||||
#include "../usb_ids.h"
|
||||
|
||||
#include "SDL_mfijoystick_c.h"
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
@ -47,9 +41,13 @@
|
|||
#import <CoreMotion/CoreMotion.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
#if defined(__MACOSX__)
|
||||
#include <IOKit/hid/IOHIDManager.h>
|
||||
#include <AppKit/NSApplication.h>
|
||||
#ifndef NSAppKitVersionNumber10_15
|
||||
#define NSAppKitVersionNumber10_15 1894
|
||||
#endif
|
||||
#endif /* __MACOSX__ */
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
#import <GameController/GameController.h>
|
||||
|
@ -64,7 +62,7 @@ static id disconnectObserver = nil;
|
|||
* they are only ever used indirectly through objc_msgSend
|
||||
*/
|
||||
@interface GCController (SDL)
|
||||
#if TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED <= 101600)
|
||||
#if defined(__MACOSX__) && (__MAC_OS_X_VERSION_MAX_ALLOWED <= 101600)
|
||||
+ (BOOL)supportsHIDDevice:(IOHIDDeviceRef)device;
|
||||
#endif
|
||||
@end
|
||||
|
@ -470,10 +468,23 @@ SDL_AppleTVRemoteRotationHintChanged(void *udata, const char *name, const char *
|
|||
}
|
||||
#endif /* TARGET_OS_TV */
|
||||
|
||||
#if defined(__MACOSX__)
|
||||
static int is_macos11(void)
|
||||
{
|
||||
return (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_15);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
IOS_JoystickInit(void)
|
||||
{
|
||||
if (@available(macos 11.0, *)) @autoreleasepool {
|
||||
#if defined(__MACOSX__)
|
||||
if (!is_macos11()) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@autoreleasepool {
|
||||
#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
|
||||
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
|
@ -1094,10 +1105,10 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
@end
|
||||
|
||||
@implementation SDL_RumbleContext {
|
||||
SDL_RumbleMotor *low_frequency_motor;
|
||||
SDL_RumbleMotor *high_frequency_motor;
|
||||
SDL_RumbleMotor *left_trigger_motor;
|
||||
SDL_RumbleMotor *right_trigger_motor;
|
||||
SDL_RumbleMotor *m_low_frequency_motor;
|
||||
SDL_RumbleMotor *m_high_frequency_motor;
|
||||
SDL_RumbleMotor *m_left_trigger_motor;
|
||||
SDL_RumbleMotor *m_right_trigger_motor;
|
||||
}
|
||||
|
||||
-(id) initWithLowFrequencyMotor:(SDL_RumbleMotor*)low_frequency_motor
|
||||
|
@ -1106,10 +1117,10 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
RightTriggerMotor:(SDL_RumbleMotor*)right_trigger_motor
|
||||
{
|
||||
self = [super init];
|
||||
self->low_frequency_motor = low_frequency_motor;
|
||||
self->high_frequency_motor = high_frequency_motor;
|
||||
self->left_trigger_motor = left_trigger_motor;
|
||||
self->right_trigger_motor = right_trigger_motor;
|
||||
self->m_low_frequency_motor = low_frequency_motor;
|
||||
self->m_high_frequency_motor = high_frequency_motor;
|
||||
self->m_left_trigger_motor = left_trigger_motor;
|
||||
self->m_right_trigger_motor = right_trigger_motor;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -1117,8 +1128,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
{
|
||||
int result = 0;
|
||||
|
||||
result += [self->low_frequency_motor setIntensity:((float)low_frequency_rumble / 65535.0f)];
|
||||
result += [self->high_frequency_motor setIntensity:((float)high_frequency_rumble / 65535.0f)];
|
||||
result += [self->m_low_frequency_motor setIntensity:((float)low_frequency_rumble / 65535.0f)];
|
||||
result += [self->m_high_frequency_motor setIntensity:((float)high_frequency_rumble / 65535.0f)];
|
||||
return ((result < 0) ? -1 : 0);
|
||||
}
|
||||
|
||||
|
@ -1126,9 +1137,9 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
{
|
||||
int result = 0;
|
||||
|
||||
if (self->left_trigger_motor && self->right_trigger_motor) {
|
||||
result += [self->left_trigger_motor setIntensity:((float)left_rumble / 65535.0f)];
|
||||
result += [self->right_trigger_motor setIntensity:((float)right_rumble / 65535.0f)];
|
||||
if (self->m_left_trigger_motor && self->m_right_trigger_motor) {
|
||||
result += [self->m_left_trigger_motor setIntensity:((float)left_rumble / 65535.0f)];
|
||||
result += [self->m_right_trigger_motor setIntensity:((float)right_rumble / 65535.0f)];
|
||||
} else {
|
||||
result = SDL_Unsupported();
|
||||
}
|
||||
|
@ -1137,8 +1148,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
|
||||
-(void)cleanup
|
||||
{
|
||||
[self->low_frequency_motor cleanup];
|
||||
[self->high_frequency_motor cleanup];
|
||||
[self->m_low_frequency_motor cleanup];
|
||||
[self->m_high_frequency_motor cleanup];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -1370,15 +1381,12 @@ IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
|||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
extern SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device);
|
||||
#if defined(SDL_JOYSTICK_MFI) && defined(__MACOSX__)
|
||||
SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
if (@available(macOS 11.0, *)) {
|
||||
if (is_macos11()) {
|
||||
return [GCController supportsHIDDevice:device] ? SDL_TRUE : SDL_FALSE;
|
||||
}
|
||||
#endif
|
||||
return SDL_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,11 +22,7 @@
|
|||
#ifndef SDL_sysjoystick_c_h_
|
||||
#define SDL_sysjoystick_c_h_
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/input.h>
|
||||
#else /* FreeBSD (and maybe others) */
|
||||
#include <dev/evdev/input.h>
|
||||
#endif
|
||||
|
||||
struct SDL_joylist_item;
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH 0x02fd
|
||||
#define USB_PRODUCT_XBOX_ONE_SERIES_X 0x0b12
|
||||
#define USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH 0x0b13
|
||||
#define USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER 0x02ff
|
||||
|
||||
/* USB usage pages */
|
||||
#define USB_USAGEPAGE_GENERIC_DESKTOP 0x0001
|
||||
|
|
|
@ -674,7 +674,7 @@ EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
|
|||
#endif
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT
|
||||
if (RAWINPUT_IsDevicePresent(vendor, product, 0)) {
|
||||
if (RAWINPUT_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) {
|
||||
/* The RAWINPUT driver is taking care of this device */
|
||||
SDL_free(pNewJoystick);
|
||||
return DIENUM_CONTINUE;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "SDL_endian.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../usb_ids.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
@ -44,17 +45,16 @@
|
|||
#include "../../core/windows/SDL_hid.h"
|
||||
#include "../hidapi/SDL_hidapijoystick_c.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#define SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
/* This requires the Windows 10 SDK to build */
|
||||
/*#define SDL_JOYSTICK_RAWINPUT_GAMING_INPUT*/
|
||||
#ifdef SDL_WINDOWS10_SDK
|
||||
#define SDL_JOYSTICK_RAWINPUT_WGI
|
||||
#endif
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
#include "../../core/windows/SDL_xinput.h"
|
||||
#endif
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
typedef struct WindowsGamingInputGamepadState WindowsGamingInputGamepadState;
|
||||
#define GamepadButtons_GUIDE 0x40000000
|
||||
|
@ -62,11 +62,13 @@ typedef struct WindowsGamingInputGamepadState WindowsGamingInputGamepadState;
|
|||
#include "windows.gaming.input.h"
|
||||
#endif
|
||||
|
||||
#if defined(SDL_JOYSTICK_RAWINPUT_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT_GAMING_INPUT)
|
||||
#if defined(SDL_JOYSTICK_RAWINPUT_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT_WGI)
|
||||
#define SDL_JOYSTICK_RAWINPUT_MATCHING
|
||||
#define SDL_JOYSTICK_RAWINPUT_MATCH_AXES
|
||||
#endif
|
||||
|
||||
/* #define DEBUG_RAWINPUT */
|
||||
/*#define DEBUG_RAWINPUT*/
|
||||
#define DEBUG_RAWINPUT
|
||||
|
||||
#ifndef RIDEV_EXINPUTSINK
|
||||
#define RIDEV_EXINPUTSINK 0x00001000
|
||||
|
@ -84,16 +86,11 @@ typedef struct WindowsGamingInputGamepadState WindowsGamingInputGamepadState;
|
|||
#define GIDC_REMOVAL 2
|
||||
#endif
|
||||
|
||||
/* external variables referenced. */
|
||||
extern HWND SDL_HelperWindow;
|
||||
|
||||
|
||||
static SDL_bool SDL_RAWINPUT_inited = SDL_FALSE;
|
||||
static int SDL_RAWINPUT_numjoysticks = 0;
|
||||
static SDL_bool SDL_RAWINPUT_need_pump = SDL_TRUE;
|
||||
static SDL_mutex *SDL_RAWINPUT_mutex = NULL;
|
||||
|
||||
static void RAWINPUT_JoystickDetect(void);
|
||||
static void RAWINPUT_PumpMessages(void);
|
||||
static void RAWINPUT_JoystickClose(SDL_Joystick *joystick);
|
||||
|
||||
typedef struct _SDL_RAWINPUT_Device
|
||||
|
@ -141,7 +138,7 @@ struct joystick_hwdata
|
|||
Uint8 xinput_slot;
|
||||
#endif
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
SDL_bool wgi_correlated;
|
||||
Uint8 wgi_correlation_id;
|
||||
Uint8 wgi_correlation_count;
|
||||
|
@ -172,11 +169,13 @@ static struct {
|
|||
} guide_button_candidate;
|
||||
|
||||
typedef struct WindowsMatchState {
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCH_AXES
|
||||
SHORT match_axes[4];
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
WORD xinput_buttons;
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
Uint32 wgi_buttons;
|
||||
#endif
|
||||
SDL_bool any_data;
|
||||
|
@ -184,8 +183,12 @@ typedef struct WindowsMatchState {
|
|||
|
||||
static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint32 match_state)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCH_AXES
|
||||
int ii;
|
||||
#endif
|
||||
|
||||
state->any_data = SDL_FALSE;
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCH_AXES
|
||||
/* SHORT state->match_axes[4] = {
|
||||
(match_state & 0x000F0000) >> 4,
|
||||
(match_state & 0x00F00000) >> 8,
|
||||
|
@ -198,6 +201,7 @@ static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint32 match_state
|
|||
state->any_data = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_MATCH_AXES */
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
/* Match axes by checking if the distance between the high 4 bits of axis and the 4 bits from match_state is 1 or less */
|
||||
|
@ -237,7 +241,7 @@ static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint32 match_state
|
|||
state->any_data = SDL_TRUE;
|
||||
#endif
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
/* Match axes by checking if the distance between the high 4 bits of axis and the 4 bits from match_state is 1 or less */
|
||||
#define WindowsGamingInputAxesMatch(gamepad) (\
|
||||
(Uint16)(((Sint16)(gamepad.LeftThumbstickX * SDL_MAX_SINT16) & 0xF000) - state->match_axes[0] + 0x1000) <= 0x2fff && \
|
||||
|
@ -341,7 +345,11 @@ RAWINPUT_XInputSlotMatches(const WindowsMatchState *state, Uint8 slot_idx)
|
|||
{
|
||||
if (xinput_state[slot_idx].connected) {
|
||||
WORD xinput_buttons = xinput_state[slot_idx].state.Gamepad.wButtons;
|
||||
if ((xinput_buttons & ~XINPUT_GAMEPAD_GUIDE) == state->xinput_buttons && XInputAxesMatch(xinput_state[slot_idx].state.Gamepad)) {
|
||||
if ((xinput_buttons & ~XINPUT_GAMEPAD_GUIDE) == state->xinput_buttons
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCH_AXES
|
||||
&& XInputAxesMatch(xinput_state[slot_idx].state.Gamepad)
|
||||
#endif
|
||||
) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +385,7 @@ RAWINPUT_GuessXInputSlot(const WindowsMatchState *state, Uint8 *correlation_id,
|
|||
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
|
||||
typedef struct WindowsGamingInputGamepadState {
|
||||
__x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad;
|
||||
|
@ -557,7 +565,11 @@ static SDL_bool
|
|||
RAWINPUT_WindowsGamingInputSlotMatches(const WindowsMatchState *state, WindowsGamingInputGamepadState *slot)
|
||||
{
|
||||
Uint32 wgi_buttons = slot->state.Buttons;
|
||||
if ((wgi_buttons & 0x3FFF) == state->wgi_buttons && WindowsGamingInputAxesMatch(slot->state)) {
|
||||
if ((wgi_buttons & 0x3FFF) == state->wgi_buttons
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCH_AXES
|
||||
&& WindowsGamingInputAxesMatch(slot->state)
|
||||
#endif
|
||||
) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
|
@ -610,49 +622,8 @@ RAWINPUT_QuitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_GAMING_INPUT */
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_WGI */
|
||||
|
||||
static int
|
||||
RAWINPUT_JoystickInit(void)
|
||||
{
|
||||
int ii;
|
||||
RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
|
||||
SDL_assert(!SDL_RAWINPUT_inited);
|
||||
SDL_assert(SDL_HelperWindow);
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, SDL_TRUE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WIN_LoadHIDDLL() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (ii = 0; ii < SDL_arraysize(subscribed_devices); ii++) {
|
||||
rid[ii].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
|
||||
rid[ii].usUsage = subscribed_devices[ii];
|
||||
rid[ii].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; /* Receive messages when in background, including device add/remove */
|
||||
rid[ii].hwndTarget = SDL_HelperWindow;
|
||||
}
|
||||
|
||||
if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
|
||||
SDL_SetError("Couldn't initialize RAWINPUT");
|
||||
WIN_UnloadHIDDLL();
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_RAWINPUT_inited = SDL_TRUE;
|
||||
|
||||
RAWINPUT_JoystickDetect();
|
||||
RAWINPUT_PumpMessages();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
RAWINPUT_JoystickGetCount(void)
|
||||
{
|
||||
return SDL_RAWINPUT_numjoysticks;
|
||||
}
|
||||
|
||||
static SDL_RAWINPUT_Device *
|
||||
RAWINPUT_AcquireDevice(SDL_RAWINPUT_Device *device)
|
||||
|
@ -664,6 +635,17 @@ RAWINPUT_AcquireDevice(SDL_RAWINPUT_Device *device)
|
|||
static void
|
||||
RAWINPUT_ReleaseDevice(SDL_RAWINPUT_Device *device)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
if (device->joystick) {
|
||||
RAWINPUT_DeviceContext *ctx = device->joystick->hwdata;
|
||||
|
||||
if (ctx->xinput_enabled && ctx->xinput_correlated) {
|
||||
RAWINPUT_MarkXInputSlotFree(ctx->xinput_slot);
|
||||
ctx->xinput_correlated = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
|
||||
|
||||
if (SDL_AtomicDecRef(&device->refcount)) {
|
||||
if (device->preparsed_data) {
|
||||
SDL_HidD_FreePreparsedData(device->preparsed_data);
|
||||
|
@ -774,7 +756,6 @@ RAWINPUT_AddDevice(HANDLE hDevice)
|
|||
|
||||
device->joystick_id = SDL_GetNextJoystickInstanceID();
|
||||
|
||||
#define DEBUG_RAWINPUT
|
||||
#ifdef DEBUG_RAWINPUT
|
||||
SDL_Log("Adding RAWINPUT device '%s' VID 0x%.4x, PID 0x%.4x, version %d, handle 0x%.8x\n", device->name, device->vendor_id, device->product_id, device->version, device->hDevice);
|
||||
#endif
|
||||
|
@ -832,29 +813,89 @@ RAWINPUT_DelDevice(SDL_RAWINPUT_Device *device, SDL_bool send_event)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
RAWINPUT_PumpMessages(void)
|
||||
static int
|
||||
RAWINPUT_JoystickInit(void)
|
||||
{
|
||||
if (SDL_RAWINPUT_need_pump) {
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, SDL_HelperWindow, WM_INPUT, WM_INPUT, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
SDL_RAWINPUT_need_pump = SDL_FALSE;
|
||||
UINT device_count = 0;
|
||||
|
||||
SDL_assert(!SDL_RAWINPUT_inited);
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, SDL_TRUE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WIN_LoadHIDDLL() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_RAWINPUT_mutex = SDL_CreateMutex();
|
||||
SDL_RAWINPUT_inited = SDL_TRUE;
|
||||
|
||||
if ((GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) && device_count > 0) {
|
||||
PRAWINPUTDEVICELIST devices = NULL;
|
||||
UINT i;
|
||||
|
||||
devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count);
|
||||
if (devices) {
|
||||
if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) {
|
||||
for (i = 0; i < device_count; ++i) {
|
||||
RAWINPUT_AddDevice(devices[i].hDevice);
|
||||
}
|
||||
}
|
||||
SDL_free(devices);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
RAWINPUT_UpdateDeviceList(void)
|
||||
static int
|
||||
RAWINPUT_JoystickGetCount(void)
|
||||
{
|
||||
MSG msg;
|
||||
/* In theory, want only WM_INPUT_DEVICE_CHANGE messages here, but PeekMessage returns nothing unless you also ask
|
||||
for WM_INPUT */
|
||||
while (PeekMessage(&msg, SDL_HelperWindow, WM_INPUT_DEVICE_CHANGE, WM_INPUT, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
return SDL_RAWINPUT_numjoysticks;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
RAWINPUT_IsEnabled()
|
||||
{
|
||||
return SDL_RAWINPUT_inited;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
|
||||
{
|
||||
SDL_RAWINPUT_Device *device;
|
||||
|
||||
/* If we're being asked about a device, that means another API just detected one, so rescan */
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
xinput_device_change = SDL_TRUE;
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
wgi_state.need_device_list_update = SDL_TRUE;
|
||||
#endif
|
||||
|
||||
device = SDL_RAWINPUT_devices;
|
||||
while (device) {
|
||||
if (vendor_id == device->vendor_id && product_id == device->product_id ) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* The Xbox 360 wireless controller shows up as product 0 in WGI */
|
||||
if (vendor_id == device->vendor_id && product_id == 0 &&
|
||||
name && SDL_strstr(device->name, name) != NULL) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* The Xbox One controller shows up as a hardcoded raw input VID/PID */
|
||||
if (name && SDL_strcmp(name, "Xbox One Game Controller") == 0 &&
|
||||
device->vendor_id == USB_VENDOR_MICROSOFT &&
|
||||
device->product_id == USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
device = device->next;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -863,7 +904,7 @@ RAWINPUT_PostUpdate(void)
|
|||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
|
||||
SDL_bool unmapped_guide_pressed = SDL_FALSE;
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
if (!wgi_state.dirty) {
|
||||
int ii;
|
||||
for (ii = 0; ii < wgi_state.per_gamepad_count; ii++) {
|
||||
|
@ -877,7 +918,6 @@ RAWINPUT_PostUpdate(void)
|
|||
wgi_state.dirty = SDL_TRUE;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
if (!xinput_state_dirty) {
|
||||
int ii;
|
||||
|
@ -917,39 +957,10 @@ RAWINPUT_PostUpdate(void)
|
|||
#endif /* SDL_JOYSTICK_RAWINPUT_MATCHING */
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
RAWINPUT_IsEnabled()
|
||||
{
|
||||
return SDL_RAWINPUT_inited;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version)
|
||||
{
|
||||
SDL_RAWINPUT_Device *device;
|
||||
|
||||
/* Make sure the device list is completely up to date when we check for device presence */
|
||||
RAWINPUT_UpdateDeviceList();
|
||||
|
||||
device = SDL_RAWINPUT_devices;
|
||||
while (device) {
|
||||
if (device->vendor_id == vendor_id && device->product_id == product_id) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
RAWINPUT_JoystickDetect(void)
|
||||
{
|
||||
/* Just ensure the window's add/remove messages have been pumped */
|
||||
RAWINPUT_UpdateDeviceList();
|
||||
|
||||
RAWINPUT_PostUpdate();
|
||||
|
||||
SDL_RAWINPUT_need_pump = SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_RAWINPUT_Device *
|
||||
|
@ -996,6 +1007,16 @@ RAWINPUT_JoystickGetDeviceInstanceID(int device_index)
|
|||
return RAWINPUT_GetDeviceByIndex(device_index)->joystick_id;
|
||||
}
|
||||
|
||||
static int
|
||||
RAWINPUT_SortValueCaps(const void *A, const void *B)
|
||||
{
|
||||
HIDP_VALUE_CAPS *capsA = (HIDP_VALUE_CAPS *)A;
|
||||
HIDP_VALUE_CAPS *capsB = (HIDP_VALUE_CAPS *)B;
|
||||
|
||||
/* Sort by Usage for single values, or UsageMax for range of values */
|
||||
return (int)capsA->NotRange.Usage - capsB->NotRange.Usage;
|
||||
}
|
||||
|
||||
static int
|
||||
RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
{
|
||||
|
@ -1025,7 +1046,7 @@ RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|||
}
|
||||
ctx->xinput_slot = XUSER_INDEX_ANY;
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
RAWINPUT_InitWindowsGamingInput(ctx);
|
||||
#endif
|
||||
}
|
||||
|
@ -1056,6 +1077,9 @@ RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|||
return SDL_SetError("Couldn't get device value capabilities");
|
||||
}
|
||||
|
||||
/* Sort the axes by usage, so X comes before Y, etc. */
|
||||
SDL_qsort(value_caps, caps.NumberInputValueCaps, sizeof(*value_caps), RAWINPUT_SortValueCaps);
|
||||
|
||||
for (i = 0; i < caps.NumberInputButtonCaps; ++i) {
|
||||
HIDP_BUTTON_CAPS *cap = &button_caps[i];
|
||||
|
||||
|
@ -1190,13 +1214,13 @@ RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|||
static int
|
||||
RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||
{
|
||||
#if defined(SDL_JOYSTICK_RAWINPUT_GAMING_INPUT) || defined(SDL_JOYSTICK_RAWINPUT_XINPUT)
|
||||
#if defined(SDL_JOYSTICK_RAWINPUT_WGI) || defined(SDL_JOYSTICK_RAWINPUT_XINPUT)
|
||||
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
|
||||
#endif
|
||||
|
||||
SDL_bool rumbled = SDL_FALSE;
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
if (!rumbled && ctx->wgi_correlated) {
|
||||
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
|
||||
HRESULT hr;
|
||||
|
@ -1233,7 +1257,23 @@ RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uin
|
|||
static int
|
||||
RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
||||
{
|
||||
#if defined(SDL_JOYSTICK_RAWINPUT_WGI)
|
||||
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
|
||||
|
||||
if (ctx->wgi_correlated) {
|
||||
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
|
||||
HRESULT hr;
|
||||
gamepad_state->vibration.LeftTrigger = (DOUBLE)left_rumble / SDL_MAX_UINT16;
|
||||
gamepad_state->vibration.RightTrigger = (DOUBLE)right_rumble / SDL_MAX_UINT16;
|
||||
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return SDL_SetError("Setting vibration failed: 0x%x\n", hr);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return SDL_Unsupported();
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
|
@ -1284,13 +1324,7 @@ RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int size)
|
|||
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
|
||||
/* Map new buttons and axes into game controller controls */
|
||||
static int axis_map[] = {
|
||||
SDL_CONTROLLER_AXIS_LEFTY,
|
||||
SDL_CONTROLLER_AXIS_LEFTX,
|
||||
SDL_CONTROLLER_AXIS_RIGHTY,
|
||||
SDL_CONTROLLER_AXIS_RIGHTX
|
||||
};
|
||||
static int button_map[] = {
|
||||
static const int button_map[] = {
|
||||
SDL_CONTROLLER_BUTTON_A,
|
||||
SDL_CONTROLLER_BUTTON_B,
|
||||
SDL_CONTROLLER_BUTTON_X,
|
||||
|
@ -1302,12 +1336,27 @@ RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int size)
|
|||
SDL_CONTROLLER_BUTTON_LEFTSTICK,
|
||||
SDL_CONTROLLER_BUTTON_RIGHTSTICK
|
||||
};
|
||||
#define HAT_MASK ((1 << SDL_CONTROLLER_BUTTON_DPAD_UP) | (1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN) | (1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT) | (1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
|
||||
static const int hat_map[] = {
|
||||
0,
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_UP),
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_UP) | (1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT),
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT),
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN) | (1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT),
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN),
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN) | (1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT),
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT),
|
||||
(1 << SDL_CONTROLLER_BUTTON_DPAD_UP) | (1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT),
|
||||
};
|
||||
Uint32 match_state = ctx->match_state;
|
||||
/* Update match_state with button bit, then fall through */
|
||||
#define SDL_PrivateJoystickButton(joystick, button, state) if (button < SDL_arraysize(button_map)) if (state) match_state |= 1 << button_map[button]; else match_state &= ~(1 << button_map[button]); SDL_PrivateJoystickButton(joystick, button, state)
|
||||
#define SDL_PrivateJoystickButton(joystick, button, state) if (button < SDL_arraysize(button_map)) { if (state) match_state |= 1 << button_map[button]; else match_state &= ~(1 << button_map[button]); } SDL_PrivateJoystickButton(joystick, button, state)
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCH_AXES
|
||||
/* Grab high 4 bits of value, then fall through */
|
||||
#define SDL_PrivateJoystickAxis(joystick, axis, value) if (axis < SDL_arraysize(axis_map)) match_state = (match_state & ~(0xF << (4 * axis_map[axis] + 16))) | ((value) & 0xF000) << (4 * axis_map[axis] + 4); SDL_PrivateJoystickAxis(joystick, axis, value)
|
||||
#define SDL_PrivateJoystickAxis(joystick, axis, value) if (axis < 4) match_state = (match_state & ~(0xF << (4 * axis + 16))) | ((value) & 0xF000) << (4 * axis + 4); SDL_PrivateJoystickAxis(joystick, axis, value)
|
||||
#endif
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_MATCHING */
|
||||
|
||||
ULONG data_length = ctx->max_data_length;
|
||||
int i;
|
||||
int nbuttons = joystick->nbuttons - (ctx->guide_hack * 1);
|
||||
|
@ -1354,13 +1403,18 @@ RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int size)
|
|||
ULONG state = item->RawValue;
|
||||
|
||||
if (state < SDL_arraysize(hat_states)) {
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
|
||||
match_state = (match_state & ~HAT_MASK) | hat_map[state];
|
||||
#endif
|
||||
SDL_PrivateJoystickHat(joystick, i, hat_states[state]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
|
||||
#ifdef SDL_PrivateJoystickButton
|
||||
#undef SDL_PrivateJoystickButton
|
||||
#endif
|
||||
#ifdef SDL_PrivateJoystickAxis
|
||||
#undef SDL_PrivateJoystickAxis
|
||||
#endif
|
||||
|
||||
|
@ -1374,11 +1428,11 @@ RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int size)
|
|||
}
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
if (!has_trigger_data && ctx->wgi_correlated) {
|
||||
has_trigger_data = SDL_TRUE;
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_GAMING_INPUT */
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_WGI */
|
||||
|
||||
if (!has_trigger_data) {
|
||||
HIDP_DATA *item = GetData(ctx->trigger_hack_index, ctx->data, data_length);
|
||||
|
@ -1424,7 +1478,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
|
||||
RAWINPUT_FillMatchState(&match_state_xinput, ctx->match_state);
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
/* Parallel logic to WINDOWS_XINPUT below */
|
||||
RAWINPUT_UpdateWindowsGamingInput();
|
||||
if (ctx->wgi_correlated) {
|
||||
|
@ -1438,7 +1492,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
let's set it to 3 to be safe. An incorrect un-correlation will simply result in lower precision
|
||||
triggers for a frame. */
|
||||
if (ctx->wgi_uncorrelate_count >= 3) {
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
#ifdef DEBUG_RAWINPUT
|
||||
SDL_Log("UN-Correlated joystick %d to WindowsGamingInput device #%d\n", joystick->instance_id, ctx->wgi_slot);
|
||||
#endif
|
||||
RAWINPUT_MarkWindowsGamingInputSlotFree(ctx->wgi_slot);
|
||||
|
@ -1470,7 +1524,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
if (new_correlation_count == 2) {
|
||||
/* correlation stayed steady and uncontested across multiple frames, guaranteed match */
|
||||
ctx->wgi_correlated = SDL_TRUE;
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
#ifdef DEBUG_RAWINPUT
|
||||
SDL_Log("Correlated joystick %d to WindowsGamingInput device #%d\n", joystick->instance_id, slot_idx);
|
||||
#endif
|
||||
correlated = SDL_TRUE;
|
||||
|
@ -1499,7 +1553,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
} else {
|
||||
correlated = SDL_TRUE;
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_GAMING_INPUT */
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_WGI */
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
|
||||
/* Parallel logic to WINDOWS_GAMING_INPUT above */
|
||||
|
@ -1531,7 +1585,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
let's set it to 3 to be safe. An incorrect un-correlation will simply result in lower precision
|
||||
triggers for a frame. */
|
||||
if (ctx->xinput_uncorrelate_count >= 3) {
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
#ifdef DEBUG_RAWINPUT
|
||||
SDL_Log("UN-Correlated joystick %d to XInput device #%d\n", joystick->instance_id, ctx->xinput_slot);
|
||||
#endif
|
||||
RAWINPUT_MarkXInputSlotFree(ctx->xinput_slot);
|
||||
|
@ -1563,7 +1617,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
if (new_correlation_count == 2) {
|
||||
/* correlation stayed steady and uncontested across multiple frames, guaranteed match */
|
||||
ctx->xinput_correlated = SDL_TRUE;
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
#ifdef DEBUG_RAWINPUT
|
||||
SDL_Log("Correlated joystick %d to XInput device #%d\n", joystick->instance_id, slot_idx);
|
||||
#endif
|
||||
correlated = SDL_TRUE;
|
||||
|
@ -1613,7 +1667,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
}
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
if (!has_trigger_data && ctx->wgi_correlated) {
|
||||
RAWINPUT_UpdateWindowsGamingInput(); /* May detect disconnect / cause uncorrelation */
|
||||
if (ctx->wgi_correlated) { /* Still connected */
|
||||
|
@ -1629,7 +1683,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
has_trigger_data = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_GAMING_INPUT */
|
||||
#endif /* SDL_JOYSTICK_RAWINPUT_WGI */
|
||||
|
||||
if (!correlated) {
|
||||
if (!guide_button_candidate.joystick ||
|
||||
|
@ -1648,8 +1702,6 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
|
|||
static void
|
||||
RAWINPUT_JoystickUpdate(SDL_Joystick *joystick)
|
||||
{
|
||||
/* Ensure data messages have been pumped */
|
||||
RAWINPUT_PumpMessages();
|
||||
RAWINPUT_UpdateOtherAPIs(joystick);
|
||||
}
|
||||
|
||||
|
@ -1677,7 +1729,7 @@ RAWINPUT_JoystickClose(SDL_Joystick *joystick)
|
|||
WIN_UnloadXInputDLL();
|
||||
}
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_GAMING_INPUT
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
|
||||
RAWINPUT_QuitWindowsGamingInput(ctx);
|
||||
#endif
|
||||
|
||||
|
@ -1697,74 +1749,115 @@ RAWINPUT_JoystickClose(SDL_Joystick *joystick)
|
|||
}
|
||||
}
|
||||
|
||||
LRESULT RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
SDL_bool
|
||||
RAWINPUT_RegisterNotifications(HWND hWnd)
|
||||
{
|
||||
if (!SDL_RAWINPUT_inited)
|
||||
return -1;
|
||||
RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
|
||||
int i;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_INPUT_DEVICE_CHANGE:
|
||||
{
|
||||
HANDLE hDevice = (HANDLE)lParam;
|
||||
switch (wParam) {
|
||||
case GIDC_ARRIVAL:
|
||||
RAWINPUT_AddDevice(hDevice);
|
||||
break;
|
||||
case GIDC_REMOVAL: {
|
||||
SDL_RAWINPUT_Device *device;
|
||||
device = RAWINPUT_DeviceFromHandle(hDevice);
|
||||
if (device) {
|
||||
RAWINPUT_DelDevice(device, SDL_TRUE);
|
||||
for (i = 0; i < SDL_arraysize(subscribed_devices); i++) {
|
||||
rid[i].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
|
||||
rid[i].usUsage = subscribed_devices[i];
|
||||
rid[i].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; /* Receive messages when in background, including device add/remove */
|
||||
rid[i].hwndTarget = hWnd;
|
||||
}
|
||||
|
||||
if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
|
||||
SDL_SetError("Couldn't register for raw input events");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
RAWINPUT_UnregisterNotifications()
|
||||
{
|
||||
int i;
|
||||
RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
|
||||
|
||||
for (i = 0; i < SDL_arraysize(subscribed_devices); i++) {
|
||||
rid[i].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
|
||||
rid[i].usUsage = subscribed_devices[i];
|
||||
rid[i].dwFlags = RIDEV_REMOVE;
|
||||
rid[i].hwndTarget = NULL;
|
||||
}
|
||||
|
||||
if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
|
||||
SDL_SetError("Couldn't unregister for raw input events");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT result = -1;
|
||||
|
||||
SDL_LockMutex(SDL_RAWINPUT_mutex);
|
||||
|
||||
if (SDL_RAWINPUT_inited) {
|
||||
switch (msg) {
|
||||
case WM_INPUT_DEVICE_CHANGE:
|
||||
{
|
||||
HANDLE hDevice = (HANDLE)lParam;
|
||||
switch (wParam) {
|
||||
case GIDC_ARRIVAL:
|
||||
RAWINPUT_AddDevice(hDevice);
|
||||
break;
|
||||
case GIDC_REMOVAL:
|
||||
{
|
||||
SDL_RAWINPUT_Device *device;
|
||||
device = RAWINPUT_DeviceFromHandle(hDevice);
|
||||
if (device) {
|
||||
RAWINPUT_DelDevice(device, SDL_TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case WM_INPUT:
|
||||
{
|
||||
Uint8 data[sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + USB_PACKET_LENGTH];
|
||||
UINT buffer_size = SDL_arraysize(data);
|
||||
case WM_INPUT:
|
||||
{
|
||||
Uint8 data[sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + USB_PACKET_LENGTH];
|
||||
UINT buffer_size = SDL_arraysize(data);
|
||||
|
||||
if ((int)GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &buffer_size, sizeof(RAWINPUTHEADER)) > 0) {
|
||||
PRAWINPUT raw_input = (PRAWINPUT)data;
|
||||
SDL_RAWINPUT_Device *device = RAWINPUT_DeviceFromHandle(raw_input->header.hDevice);
|
||||
if (device) {
|
||||
SDL_Joystick *joystick = device->joystick;
|
||||
if (joystick) {
|
||||
RAWINPUT_HandleStatePacket(joystick, raw_input->data.hid.bRawData, raw_input->data.hid.dwSizeHid);
|
||||
if ((int)GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &buffer_size, sizeof(RAWINPUTHEADER)) > 0) {
|
||||
PRAWINPUT raw_input = (PRAWINPUT)data;
|
||||
SDL_RAWINPUT_Device *device = RAWINPUT_DeviceFromHandle(raw_input->header.hDevice);
|
||||
if (device) {
|
||||
SDL_Joystick *joystick = device->joystick;
|
||||
if (joystick) {
|
||||
RAWINPUT_HandleStatePacket(joystick, raw_input->data.hid.bRawData, raw_input->data.hid.dwSizeHid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
||||
SDL_UnlockMutex(SDL_RAWINPUT_mutex);
|
||||
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
return CallWindowProc(DefWindowProc, hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
static void
|
||||
RAWINPUT_JoystickQuit(void)
|
||||
{
|
||||
int ii;
|
||||
RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
|
||||
|
||||
if (!SDL_RAWINPUT_inited)
|
||||
if (!SDL_RAWINPUT_inited) {
|
||||
return;
|
||||
|
||||
for (ii = 0; ii < SDL_arraysize(subscribed_devices); ii++) {
|
||||
rid[ii].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
|
||||
rid[ii].usUsage = subscribed_devices[ii];
|
||||
rid[ii].dwFlags = RIDEV_REMOVE;
|
||||
rid[ii].hwndTarget = NULL;
|
||||
}
|
||||
|
||||
if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
|
||||
SDL_Log("Couldn't un-register RAWINPUT");
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_RAWINPUT_mutex);
|
||||
|
||||
while (SDL_RAWINPUT_devices) {
|
||||
RAWINPUT_DelDevice(SDL_RAWINPUT_devices, SDL_FALSE);
|
||||
}
|
||||
|
@ -1774,6 +1867,10 @@ RAWINPUT_JoystickQuit(void)
|
|||
SDL_RAWINPUT_numjoysticks = 0;
|
||||
|
||||
SDL_RAWINPUT_inited = SDL_FALSE;
|
||||
|
||||
SDL_UnlockMutex(SDL_RAWINPUT_mutex);
|
||||
SDL_DestroyMutex(SDL_RAWINPUT_mutex);
|
||||
SDL_RAWINPUT_mutex = NULL;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
|
|
|
@ -19,15 +19,20 @@
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
/* Return true if the RawInput driver is enabled */
|
||||
extern SDL_bool RAWINPUT_IsEnabled();
|
||||
|
||||
/* Return true if a RawInput device is present and supported as a joystick */
|
||||
extern SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version);
|
||||
extern SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
|
||||
|
||||
/* Registers for input events */
|
||||
extern SDL_bool RAWINPUT_RegisterNotifications(HWND hWnd);
|
||||
extern void RAWINPUT_UnregisterNotifications();
|
||||
|
||||
/* Returns 0 if message was handled */
|
||||
extern LRESULT RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
extern LRESULT CALLBACK RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -120,7 +120,7 @@ SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
|
|||
|
||||
for (i = 0; i < raw_device_count; i++) {
|
||||
RID_DEVICE_INFO rdi;
|
||||
char devName[128];
|
||||
char devName[MAX_PATH];
|
||||
UINT rdiSize = sizeof(rdi);
|
||||
UINT nameSize = SDL_arraysize(devName);
|
||||
|
||||
|
@ -249,7 +249,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
|
|||
#endif
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT
|
||||
if (!ignore_joystick && RAWINPUT_IsDevicePresent(vendor, product, version)) {
|
||||
if (!ignore_joystick && RAWINPUT_IsDevicePresent(vendor, product, version, name)) {
|
||||
ignore_joystick = SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "SDL_windowsjoystick_c.h"
|
||||
#include "SDL_dinputjoystick_c.h"
|
||||
#include "SDL_xinputjoystick_c.h"
|
||||
#include "SDL_rawinputjoystick_c.h"
|
||||
|
||||
#include "../../haptic/windows/SDL_dinputhaptic_c.h" /* For haptic hot plugging */
|
||||
#include "../../haptic/windows/SDL_xinputhaptic_c.h" /* For haptic hot plugging */
|
||||
|
@ -109,9 +110,9 @@ typedef struct
|
|||
|
||||
/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
|
||||
static LRESULT CALLBACK
|
||||
SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
SDL_PrivateJoystickDetectProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
switch (msg) {
|
||||
case WM_DEVICECHANGE:
|
||||
switch (wParam) {
|
||||
case DBT_DEVICEARRIVAL:
|
||||
|
@ -130,12 +131,20 @@ SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc (hwnd, message, wParam, lParam);
|
||||
#if SDL_JOYSTICK_RAWINPUT
|
||||
return CallWindowProc(RAWINPUT_WindowProc, hwnd, msg, wParam, lParam);
|
||||
#else
|
||||
return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
|
||||
{
|
||||
#if SDL_JOYSTICK_RAWINPUT
|
||||
RAWINPUT_UnregisterNotifications();
|
||||
#endif
|
||||
|
||||
if (data->hNotify)
|
||||
UnregisterDeviceNotification(data->hNotify);
|
||||
|
||||
|
@ -188,6 +197,10 @@ SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
|
|||
SDL_CleanupDeviceNotification(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if SDL_JOYSTICK_RAWINPUT
|
||||
RAWINPUT_RegisterNotifications(data->messageWindow);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ GuessXInputDevice(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 *pVersion)
|
|||
|
||||
for (i = 0; i < device_count; i++) {
|
||||
RID_DEVICE_INFO rdi;
|
||||
char devName[128];
|
||||
char devName[MAX_PATH];
|
||||
UINT rdiSize = sizeof(rdi);
|
||||
UINT nameSize = SDL_arraysize(devName);
|
||||
|
||||
|
@ -302,7 +302,7 @@ AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
|
|||
#endif
|
||||
|
||||
#ifdef SDL_JOYSTICK_RAWINPUT
|
||||
if (RAWINPUT_IsDevicePresent(vendor, product, version)) {
|
||||
if (RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)) {
|
||||
/* The RAWINPUT driver is taking care of this device */
|
||||
SDL_free(pNewJoystick);
|
||||
return;
|
||||
|
|
|
@ -531,6 +531,85 @@ SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen)
|
|||
#endif /* HAVE_WCSNCMP */
|
||||
}
|
||||
|
||||
int
|
||||
SDL_wcscasecmp(const wchar_t *str1, const wchar_t *str2)
|
||||
{
|
||||
#if defined(HAVE_WCSCASECMP)
|
||||
return wcscasecmp(str1, str2);
|
||||
#elif defined(HAVE__WCSICMP)
|
||||
return _wcsicmp(str1, str2);
|
||||
#else
|
||||
wchar_t a = 0;
|
||||
wchar_t b = 0;
|
||||
while (*str1 && *str2) {
|
||||
/* FIXME: This doesn't actually support wide characters */
|
||||
if (*str1 >= 0x80 || *str2 >= 0x80) {
|
||||
a = *str1;
|
||||
b = *str2;
|
||||
} else {
|
||||
a = SDL_toupper((unsigned char) *str1);
|
||||
b = SDL_toupper((unsigned char) *str2);
|
||||
}
|
||||
if (a != b)
|
||||
break;
|
||||
++str1;
|
||||
++str2;
|
||||
}
|
||||
|
||||
/* FIXME: This doesn't actually support wide characters */
|
||||
if (*str1 >= 0x80 || *str2 >= 0x80) {
|
||||
a = *str1;
|
||||
b = *str2;
|
||||
} else {
|
||||
a = SDL_toupper((unsigned char) *str1);
|
||||
b = SDL_toupper((unsigned char) *str2);
|
||||
}
|
||||
return (int) ((unsigned int) a - (unsigned int) b);
|
||||
#endif /* HAVE__WCSICMP */
|
||||
}
|
||||
|
||||
int
|
||||
SDL_wcsncasecmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen)
|
||||
{
|
||||
#if defined(HAVE_WCSNCASECMP)
|
||||
return wcsncasecmp(str1, str2, maxlen);
|
||||
#elif defined(HAVE__WCSNICMP)
|
||||
return _wcsnicmp(str1, str2, maxlen);
|
||||
#else
|
||||
wchar_t a = 0;
|
||||
wchar_t b = 0;
|
||||
while (*str1 && *str2 && maxlen) {
|
||||
/* FIXME: This doesn't actually support wide characters */
|
||||
if (*str1 >= 0x80 || *str2 >= 0x80) {
|
||||
a = *str1;
|
||||
b = *str2;
|
||||
} else {
|
||||
a = SDL_toupper((unsigned char) *str1);
|
||||
b = SDL_toupper((unsigned char) *str2);
|
||||
}
|
||||
if (a != b)
|
||||
break;
|
||||
++str1;
|
||||
++str2;
|
||||
--maxlen;
|
||||
}
|
||||
|
||||
if (maxlen == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
/* FIXME: This doesn't actually support wide characters */
|
||||
if (*str1 >= 0x80 || *str2 >= 0x80) {
|
||||
a = *str1;
|
||||
b = *str2;
|
||||
} else {
|
||||
a = SDL_toupper((unsigned char) *str1);
|
||||
b = SDL_toupper((unsigned char) *str2);
|
||||
}
|
||||
return (int) ((unsigned int) a - (unsigned int) b);
|
||||
}
|
||||
#endif /* HAVE__WCSNICMP */
|
||||
}
|
||||
|
||||
size_t
|
||||
SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen)
|
||||
{
|
||||
|
|
|
@ -314,6 +314,11 @@ SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
|
|||
return SDL_SetError("SDL_FillRect(): Unsupported surface format");
|
||||
}
|
||||
|
||||
/* Nothing to do */
|
||||
if (dst->w == 0 || dst->h == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform software fill */
|
||||
if (!dst->pixels) {
|
||||
return SDL_SetError("SDL_FillRect(): You must lock the surface");
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
#include "../../joystick/windows/SDL_rawinputjoystick_c.h"
|
||||
#include "SDL_windowsvideo.h"
|
||||
#include "SDL_windowswindow.h"
|
||||
#include "SDL_hints.h"
|
||||
|
@ -811,18 +810,8 @@ WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
|||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK SDL_HelperWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
#if SDL_JOYSTICK_RAWINPUT
|
||||
if (RAWINPUT_WindowProc(hWnd, msg, wParam, lParam) == 0) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a HelperWindow used for DirectInput and RawInput events.
|
||||
* Creates a HelperWindow used for DirectInput.
|
||||
*/
|
||||
int
|
||||
SDL_HelperWindowCreate(void)
|
||||
|
@ -837,7 +826,7 @@ SDL_HelperWindowCreate(void)
|
|||
|
||||
/* Create the class. */
|
||||
SDL_zero(wce);
|
||||
wce.lpfnWndProc = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, SDL_TRUE) ? SDL_HelperWindowProc : DefWindowProc;
|
||||
wce.lpfnWndProc = DefWindowProc;
|
||||
wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
|
||||
wce.hInstance = hInstance;
|
||||
|
||||
|
|
Loading…
Reference in New Issue