early-access version 2281

This commit is contained in:
pineappleEA
2021-12-07 02:20:09 +01:00
parent c2ae6d480a
commit c4fa174d53
591 changed files with 36978 additions and 18653 deletions

View File

@@ -1515,6 +1515,57 @@ SDL_GameControllerNumMappings(void)
return num_mappings;
}
/*
* Create a mapping string for a mapping
*/
static char *
CreateMappingString(ControllerMapping_t *mapping, SDL_JoystickGUID guid)
{
char *pMappingString, *pPlatformString;
char pchGUID[33];
size_t needed;
const char *platform = SDL_GetPlatform();
SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID));
/* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */
needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1;
if (!SDL_strstr(mapping->mapping, SDL_CONTROLLER_PLATFORM_FIELD)) {
/* add memory for ',' + platform:PLATFORM */
if (mapping->mapping[SDL_strlen(mapping->mapping) - 1] != ',') {
needed += 1;
}
needed += SDL_strlen(SDL_CONTROLLER_PLATFORM_FIELD) + SDL_strlen(platform);
}
pMappingString = SDL_malloc(needed);
if (!pMappingString) {
SDL_OutOfMemory();
return NULL;
}
SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping);
if (!SDL_strstr(mapping->mapping, SDL_CONTROLLER_PLATFORM_FIELD)) {
if (mapping->mapping[SDL_strlen(mapping->mapping) - 1] != ',') {
SDL_strlcat(pMappingString, ",", needed);
}
SDL_strlcat(pMappingString, SDL_CONTROLLER_PLATFORM_FIELD, needed);
SDL_strlcat(pMappingString, platform, needed);
}
/* Make sure multiple platform strings haven't made their way into the mapping */
pPlatformString = SDL_strstr(pMappingString, SDL_CONTROLLER_PLATFORM_FIELD);
if (pPlatformString) {
pPlatformString = SDL_strstr(pPlatformString + 1, SDL_CONTROLLER_PLATFORM_FIELD);
if (pPlatformString) {
*pPlatformString = '\0';
}
}
return pMappingString;
}
/*
* Get the mapping at a particular index.
*/
@@ -1528,20 +1579,7 @@ SDL_GameControllerMappingForIndex(int mapping_index)
continue;
}
if (mapping_index == 0) {
char *pMappingString;
char pchGUID[33];
size_t needed;
SDL_JoystickGetGUIDString(mapping->guid, pchGUID, sizeof(pchGUID));
/* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */
needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1;
pMappingString = SDL_malloc(needed);
if (!pMappingString) {
SDL_OutOfMemory();
return NULL;
}
SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping);
return pMappingString;
return CreateMappingString(mapping, mapping->guid);
}
--mapping_index;
}
@@ -1554,22 +1592,11 @@ SDL_GameControllerMappingForIndex(int mapping_index)
char *
SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid)
{
char *pMappingString = NULL;
ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(guid, SDL_FALSE);
if (mapping) {
char pchGUID[33];
size_t needed;
SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID));
/* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */
needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1;
pMappingString = SDL_malloc(needed);
if (!pMappingString) {
SDL_OutOfMemory();
return NULL;
}
SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping);
return CreateMappingString(mapping, guid);
}
return pMappingString;
return NULL;
}
/*
@@ -1793,6 +1820,13 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid)
}
#endif
#if defined(__ANDROID__)
if (name && SDL_strcmp(name, "uinput-fpc") == 0) {
/* The Google Pixel fingerprint sensor reports itself as a joystick */
return SDL_TRUE;
}
#endif
if (SDL_allowed_controllers.num_entries == 0 &&
SDL_ignored_controllers.num_entries == 0) {
return SDL_FALSE;
@@ -2447,6 +2481,18 @@ SDL_GameControllerHasLED(SDL_GameController *gamecontroller)
return SDL_JoystickHasLED(SDL_GameControllerGetJoystick(gamecontroller));
}
SDL_bool
SDL_GameControllerHasRumble(SDL_GameController *gamecontroller)
{
return SDL_JoystickHasRumble(SDL_GameControllerGetJoystick(gamecontroller));
}
SDL_bool
SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller)
{
return SDL_JoystickHasRumbleTriggers(SDL_GameControllerGetJoystick(gamecontroller));
}
int
SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue)
{
@@ -2675,4 +2721,26 @@ SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick)
}
}
const char *
SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button)
{
#if defined(SDL_JOYSTICK_MFI)
const char *IOS_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button);
return IOS_GameControllerGetAppleSFSymbolsNameForButton(gamecontroller, button);
#else
return NULL;
#endif
}
const char *
SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis)
{
#if defined(SDL_JOYSTICK_MFI)
const char *IOS_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
return IOS_GameControllerGetAppleSFSymbolsNameForAxis(gamecontroller, axis);
#else
return NULL;
#endif
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -26,7 +26,7 @@
The easiest way to generate a new mapping is to start Steam in Big Picture
mode, configure your joystick and then look in config/config.vdf in your
Steam installation directory for the "SDL_GamepadBind" entry.
Alternatively, you can use the app located in test/controllermap
*/
static const char *s_ControllerMappings [] =
@@ -135,7 +135,7 @@ static const char *s_ControllerMappings [] =
"78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,",
"03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,",
"03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,",
"03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,",
"03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
"030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000300f00000b01000000000000,GGE909 Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
"03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
@@ -248,7 +248,7 @@ static const char *s_ControllerMappings [] =
"030000003807000056a8000000000000,PS3 RF pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,",
"030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
@@ -396,7 +396,7 @@ static const char *s_ControllerMappings [] =
"030000000d0f00008500000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,",
"03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,",
"03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
@@ -482,6 +482,7 @@ static const char *s_ControllerMappings [] =
"030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
"030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
"030000005e040000200b000011050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
@@ -556,8 +557,9 @@ static const char *s_ControllerMappings [] =
"03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"03000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,",
"05000000503200000110000000000000,Atari Classic Controller,a:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,x:b1,",
"03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,",
"03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,",
"05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,",
"030000005e0400008e02000047010000,Atari Xbox 360 Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:,lefty:,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:,righty:,start:b9,x:b0,y:b3,",
@@ -589,6 +591,7 @@ static const char *s_ControllerMappings [] =
"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"030000000d0f00005001000009040000,HORI Fighting Commander OCTA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000000d0f00008400000011010000,HORI Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000000d0f00008500000010010000,HORI Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
@@ -695,8 +698,9 @@ static const char *s_ControllerMappings [] =
"050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,",
"030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004c050000e60c000011810000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,",
"050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,",
"030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,",
"03000000c62400003a54000001010000,PowerA XBox One Controller,a:b0,b:b1,back:b6,dpdown:h0.7,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",

View File

@@ -343,6 +343,9 @@ SDL_JoystickGetDevicePlayerIndex(int device_index)
static SDL_bool
SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
{
#ifdef __WINRT__
return SDL_TRUE;
#else
static Uint32 zero_centered_joysticks[] = {
MAKE_VIDPID(0x0e8f, 0x3013), /* HuiJia SNES USB adapter */
MAKE_VIDPID(0x05a0, 0x3232), /* 8Bitdo Zero Gamepad */
@@ -365,6 +368,7 @@ SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
}
}
return SDL_FALSE;
#endif /* __WINRT__ */
}
/*
@@ -759,7 +763,7 @@ SDL_JoystickGetButton(SDL_Joystick *joystick, int button)
SDL_bool
SDL_JoystickGetAttached(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
if (!joystick) {
return SDL_FALSE;
}
@@ -944,7 +948,43 @@ SDL_JoystickHasLED(SDL_Joystick *joystick)
SDL_LockJoysticks();
result = joystick->driver->HasLED(joystick);
result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_LED) != 0;
SDL_UnlockJoysticks();
return result;
}
SDL_bool
SDL_JoystickHasRumble(SDL_Joystick *joystick)
{
SDL_bool result;
if (!SDL_PrivateJoystickValid(joystick)) {
return SDL_FALSE;
}
SDL_LockJoysticks();
result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE) != 0;
SDL_UnlockJoysticks();
return result;
}
SDL_bool
SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick)
{
SDL_bool result;
if (!SDL_PrivateJoystickValid(joystick)) {
return SDL_FALSE;
}
SDL_LockJoysticks();
result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE_TRIGGERS) != 0;
SDL_UnlockJoysticks();
@@ -1095,8 +1135,8 @@ SDL_JoystickQuit(void)
SDL_JoystickClose(SDL_joysticks);
}
/* Quit the joystick setup */
for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
/* Quit drivers in reverse order to avoid breaking dependencies between drivers */
for (i = SDL_arraysize(SDL_joystick_drivers) - 1; i >= 0; --i) {
SDL_joystick_drivers[i]->Quit();
}
@@ -1344,7 +1384,7 @@ SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
info->value = value;
info->zero = value;
info->has_initial_value = SDL_TRUE;
} else if (value == info->value) {
} else if (value == info->value && !info->sending_initial_value) {
return 0;
} else {
info->has_second_value = SDL_TRUE;
@@ -1356,15 +1396,17 @@ SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
return 0;
}
info->sent_initial_value = SDL_TRUE;
info->value = ~value; /* Just so we pass the check above */
info->sending_initial_value = SDL_TRUE;
SDL_PrivateJoystickAxis(joystick, axis, info->initial_value);
info->sending_initial_value = SDL_FALSE;
}
/* We ignore events if we don't have keyboard focus, except for centering
* events.
*/
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
if ((value > info->zero && value >= info->value) ||
if (info->sending_initial_value ||
(value > info->zero && value >= info->value) ||
(value < info->zero && value <= info->value)) {
return 0;
}
@@ -1757,8 +1799,13 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c
size_t prefixlen = SDL_strlen(replacements[i].prefix);
if (SDL_strncasecmp(name, replacements[i].prefix, prefixlen) == 0) {
size_t replacementlen = SDL_strlen(replacements[i].replacement);
SDL_memcpy(name, replacements[i].replacement, replacementlen);
SDL_memmove(name+replacementlen, name+prefixlen, (len-prefixlen+1));
if (replacementlen <= prefixlen) {
SDL_memcpy(name, replacements[i].replacement, replacementlen);
SDL_memmove(name+replacementlen, name+prefixlen, (len-prefixlen)+1);
len -= (prefixlen - replacementlen);
} else {
/* FIXME: Need to handle the expand case by reallocating the string */
}
break;
}
}
@@ -1768,11 +1815,9 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c
int matchlen = PrefixMatch(name, &name[i]);
if (matchlen > 0 && name[matchlen-1] == ' ') {
SDL_memmove(name, name+matchlen, len-matchlen+1);
len -= matchlen;
break;
} else if (matchlen > 0 && name[matchlen] == ' ') {
SDL_memmove(name, name+matchlen+1, len-matchlen);
len -= (matchlen + 1);
break;
}
}
@@ -1961,7 +2006,7 @@ SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_SERIES_X ||
product_id == USB_PRODUCT_XBOX_SERIES_X_BLUETOOTH) {
product_id == USB_PRODUCT_XBOX_SERIES_X_BLE) {
return SDL_TRUE;
}
}
@@ -1986,10 +2031,14 @@ SDL_bool
SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
if (product_id == USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH ||
product_id == USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLE ||
product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLE ||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH ||
product_id == USB_PRODUCT_XBOX_SERIES_X_BLUETOOTH) {
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLE ||
product_id == USB_PRODUCT_XBOX_SERIES_X_BLE) {
return SDL_TRUE;
}
}
@@ -2389,8 +2438,9 @@ SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
/* Additional entries */
/*****************************************************************/
/* Anne Pro II Keyboard */
MAKE_VIDPID(0x04d9, 0x8009), /* OBINLB USB-HID Keyboard */
MAKE_VIDPID(0x0b05, 0x1958), /* ROG Chakram Mouse */
MAKE_VIDPID(0x26ce, 0x01a2), /* ASRock LED Controller */
};
unsigned int i;
@@ -2713,6 +2763,13 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger
}
#endif
/* We ignore events if we don't have keyboard focus, except for touch release */
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
if (event_type != SDL_CONTROLLERTOUCHPADUP) {
return 0;
}
}
/* Update internal joystick state */
finger_info->state = state;
finger_info->x = x;
@@ -2742,6 +2799,11 @@ int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const
int i;
int posted = 0;
/* We ignore events if we don't have keyboard focus */
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
return 0;
}
for (i = 0; i < joystick->nsensors; ++i) {
SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];

View File

@@ -36,6 +36,7 @@ typedef struct _SDL_JoystickAxisInfo
SDL_bool has_initial_value; /* Whether we've seen a value on the axis yet */
SDL_bool has_second_value; /* Whether we've seen a second value on the axis yet */
SDL_bool sent_initial_value; /* Whether we've sent the initial axis value */
SDL_bool sending_initial_value; /* Whether we are sending the initial axis value */
} SDL_JoystickAxisInfo;
typedef struct _SDL_JoystickTouchpadFingerInfo
@@ -120,6 +121,11 @@ struct _SDL_Joystick
#define SDL_HARDWARE_BUS_USB 0x03
#define SDL_HARDWARE_BUS_BLUETOOTH 0x05
/* Joystick capability flags for GetCapabilities() */
#define SDL_JOYCAP_LED 0x01
#define SDL_JOYCAP_RUMBLE 0x02
#define SDL_JOYCAP_RUMBLE_TRIGGERS 0x04
/* Macro to combine a USB vendor ID and product ID into a single Uint32 value */
#define MAKE_VIDPID(VID, PID) (((Uint32)(VID))<<16|(PID))
@@ -163,8 +169,10 @@ typedef struct _SDL_JoystickDriver
int (*Rumble)(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
int (*RumbleTriggers)(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble);
/* Capability detection */
Uint32 (*GetCapabilities)(SDL_Joystick *joystick);
/* LED functionality */
SDL_bool (*HasLED)(SDL_Joystick *joystick);
int (*SetLED)(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
/* General effects */

View File

@@ -616,10 +616,10 @@ ANDROID_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint1
return SDL_Unsupported();
}
static SDL_bool
ANDROID_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
ANDROID_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
static int
@@ -719,7 +719,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver =
ANDROID_JoystickOpen,
ANDROID_JoystickRumble,
ANDROID_JoystickRumbleTriggers,
ANDROID_JoystickHasLED,
ANDROID_JoystickGetCapabilities,
ANDROID_JoystickSetLED,
ANDROID_JoystickSendEffect,
ANDROID_JoystickSetSensorsEnabled,

View File

@@ -240,7 +240,7 @@ BSD_JoystickInit(void)
}
for (i = 0; i < MAX_JOY_JOYS; i++) {
SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
fd = open(s, O_RDONLY);
fd = open(s, O_RDONLY | O_CLOEXEC);
if (fd != -1) {
joynames[numjoysticks++] = SDL_strdup(s);
close(fd);
@@ -357,7 +357,7 @@ BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
int fd;
int i;
fd = open(path, O_RDONLY);
fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
return SDL_SetError("%s: %s", path, strerror(errno));
}
@@ -426,7 +426,7 @@ BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
str[i] = UGETW(usd.usd_desc.bString[i]);
}
str[i] = '\0';
asprintf(&new_name, "%s @ %s", str, path);
SDL_asprintf(&new_name, "%s @ %s", str, path);
if (new_name != NULL) {
SDL_free(joydevnames[numjoysticks]);
joydevnames[numjoysticks] = new_name;
@@ -552,7 +552,7 @@ BSD_JoystickUpdate(SDL_Joystick *joy)
if (joy->hwdata->type == BSDJOY_JOY) {
while (read(joy->hwdata->fd, &gameport, sizeof gameport) == sizeof gameport) {
if (abs(x - gameport.x) > 8) {
if (SDL_abs(x - gameport.x) > 8) {
x = gameport.x;
if (x < xmin) {
xmin = x;
@@ -569,7 +569,7 @@ BSD_JoystickUpdate(SDL_Joystick *joy)
v *= 32768 / ((xmax - xmin + 1) / 2);
SDL_PrivateJoystickAxis(joy, 0, v);
}
if (abs(y - gameport.y) > 8) {
if (SDL_abs(y - gameport.y) > 8) {
y = gameport.y;
if (y < ymin) {
ymin = y;
@@ -777,10 +777,10 @@ BSD_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
return SDL_FALSE;
}
static SDL_bool
BSD_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
BSD_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
static int
@@ -814,7 +814,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver =
BSD_JoystickOpen,
BSD_JoystickRumble,
BSD_JoystickRumbleTriggers,
BSD_JoystickHasLED,
BSD_JoystickGetCapabilities,
BSD_JoystickSetLED,
BSD_JoystickSendEffect,
BSD_JoystickSetSensorsEnabled,

View File

@@ -325,9 +325,15 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with XBOXGIP driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b02 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0a ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0c ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft X-Box Series X pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft X-Box Series X pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft X-Box Series X pad (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b20 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b21 ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b22 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (BLE)
{ MAKE_CONTROLLER_ID( 0x0738, 0x4a01 ), k_eControllerType_XBoxOneController, NULL }, // Mad Catz FightStick TE 2
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0139 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x013B ), k_eControllerType_XBoxOneController, "PDP Xbox One Face-Off Controller" }, // PDP Face-Off Gamepad for Xbox One
@@ -579,7 +585,7 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0181 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Deluxe Wired Pro Controller for Nintendo Switch
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0184 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Deluxe+ Audio Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0185 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Wired Fight Pad Pro for Nintendo Switch
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0186 ), k_eControllerType_SwitchProController, NULL }, // PDP Afterglow Wireless Switch Controller - working gyro. USB is for charging only. Many later "Wireless" line devices w/ gyro also use this vid/pid
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0186 ), k_eControllerType_SwitchProController, NULL }, // PDP Afterglow Wireless Switch Controller - working gyro. USB is for charging only. Many later "Wireless" line devices w/ gyro also use this vid/pid
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0187 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Rockcandy Wired Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0188 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Afterglow Wired Deluxe+ Audio Controller
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00aa ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORI Real Arcade Pro V Hayabusa in Switch Mode

View File

@@ -939,10 +939,21 @@ DARWIN_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16
return SDL_Unsupported();
}
static SDL_bool
DARWIN_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
DARWIN_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
recDevice *device = joystick->hwdata;
Uint32 result = 0;
if (!device) {
return 0;
}
if (device->ffservice) {
result |= SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -1111,7 +1122,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver =
DARWIN_JoystickOpen,
DARWIN_JoystickRumble,
DARWIN_JoystickRumbleTriggers,
DARWIN_JoystickHasLED,
DARWIN_JoystickGetCapabilities,
DARWIN_JoystickSetLED,
DARWIN_JoystickSendEffect,
DARWIN_JoystickSetSensorsEnabled,

View File

@@ -95,10 +95,10 @@ DUMMY_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16
return SDL_Unsupported();
}
static SDL_bool
DUMMY_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
DUMMY_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
static int
@@ -153,7 +153,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver =
DUMMY_JoystickOpen,
DUMMY_JoystickRumble,
DUMMY_JoystickRumbleTriggers,
DUMMY_JoystickHasLED,
DUMMY_JoystickGetCapabilities,
DUMMY_JoystickSetLED,
DUMMY_JoystickSendEffect,
DUMMY_JoystickSetSensorsEnabled,

View File

@@ -414,10 +414,10 @@ EMSCRIPTEN_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
return SDL_FALSE;
}
static SDL_bool
EMSCRIPTEN_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
EMSCRIPTEN_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
static int
@@ -451,7 +451,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver =
EMSCRIPTEN_JoystickOpen,
EMSCRIPTEN_JoystickRumble,
EMSCRIPTEN_JoystickRumbleTriggers,
EMSCRIPTEN_JoystickHasLED,
EMSCRIPTEN_JoystickGetCapabilities,
EMSCRIPTEN_JoystickSetLED,
EMSCRIPTEN_JoystickSendEffect,
EMSCRIPTEN_JoystickSetSensorsEnabled,

View File

@@ -271,9 +271,9 @@ extern "C"
return SDL_FALSE;
}
static SDL_bool HAIKU_JoystickHasLED(SDL_Joystick *joystick)
static Uint32 HAIKU_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
static int HAIKU_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
@@ -305,7 +305,7 @@ extern "C"
HAIKU_JoystickOpen,
HAIKU_JoystickRumble,
HAIKU_JoystickRumbleTriggers,
HAIKU_JoystickHasLED,
HAIKU_JoystickGetCapabilities,
HAIKU_JoystickSetLED,
HAIKU_JoystickSendEffect,
HAIKU_JoystickSetSensorsEnabled,

View File

@@ -32,7 +32,7 @@
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
#include "../../hidapi/SDL_hidapi.h"
#include "../../hidapi/SDL_hidapi_c.h"
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
@@ -129,7 +129,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -154,7 +154,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
}
} else {
/* This is all that's needed to initialize the device. Really! */
if (hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
SDL_SetError("Couldn't initialize WUP-028");
goto error;
}
@@ -163,7 +163,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
SDL_Delay(10);
/* Add all the applicable joysticks */
while ((size = hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
#ifdef DEBUG_GAMECUBE_PROTOCOL
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
#endif
@@ -204,7 +204,7 @@ error:
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
if (device->context) {
@@ -389,7 +389,7 @@ HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
int size;
/* Read input packet */
while ((size = hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
#ifdef DEBUG_GAMECUBE_PROTOCOL
//HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
#endif
@@ -464,10 +464,26 @@ HIDAPI_DriverGameCube_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joys
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverGameCube_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverGameCube_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_FALSE;
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
Uint32 result = 0;
if (!ctx->pc_mode) {
Uint8 i;
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
if (joystick->instance_id == ctx->joysticks[i]) {
if (!ctx->wireless[i] && ctx->rumbleAllowed[i]) {
result |= SDL_JOYCAP_RUMBLE;
break;
}
}
}
}
return result;
}
static int
@@ -510,7 +526,7 @@ HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -523,6 +539,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
{
SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverGameCube_IsSupportedDevice,
HIDAPI_DriverGameCube_GetDeviceName,
HIDAPI_DriverGameCube_InitDevice,
@@ -532,7 +549,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
HIDAPI_DriverGameCube_OpenJoystick,
HIDAPI_DriverGameCube_RumbleJoystick,
HIDAPI_DriverGameCube_RumbleJoystickTriggers,
HIDAPI_DriverGameCube_HasJoystickLED,
HIDAPI_DriverGameCube_GetJoystickCapabilities,
HIDAPI_DriverGameCube_SetJoystickLED,
HIDAPI_DriverGameCube_SendJoystickEffect,
HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,

View File

@@ -87,7 +87,7 @@ HIDAPI_DriverLuna_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
SDL_free(ctx);
@@ -132,10 +132,16 @@ HIDAPI_DriverLuna_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverLuna_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverLuna_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_FALSE;
Uint32 result = 0;
if (device->product_id == BLUETOOTH_PRODUCT_LUNA_CONTROLLER) {
result |= SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -386,7 +392,7 @@ HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_LUNA_PROTOCOL
HIDAPI_DumpPacket("Amazon Luna packet: size = %d", data, size);
#endif
@@ -413,7 +419,7 @@ HIDAPI_DriverLuna_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
@@ -432,6 +438,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna =
{
SDL_HINT_JOYSTICK_HIDAPI_LUNA,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverLuna_IsSupportedDevice,
HIDAPI_DriverLuna_GetDeviceName,
HIDAPI_DriverLuna_InitDevice,
@@ -441,7 +448,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna =
HIDAPI_DriverLuna_OpenJoystick,
HIDAPI_DriverLuna_RumbleJoystick,
HIDAPI_DriverLuna_RumbleJoystickTriggers,
HIDAPI_DriverLuna_HasJoystickLED,
HIDAPI_DriverLuna_GetJoystickCapabilities,
HIDAPI_DriverLuna_SetJoystickLED,
HIDAPI_DriverLuna_SendJoystickEffect,
HIDAPI_DriverLuna_SetJoystickSensorsEnabled,

View File

@@ -163,11 +163,11 @@ HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return NULL;
}
static int ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
report[0] = report_id;
return hid_get_feature_report(dev, report, length);
return SDL_hid_get_feature_report(dev, report, length);
}
static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
@@ -415,7 +415,7 @@ HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
/* This is just a dummy packet that should have no effect, since we don't set the CRC */
Uint8 data[78];
SDL_zero(data);
SDL_zeroa(data);
data[0] = k_EPS4ReportIdBluetoothEffects;
data[1] = 0xC0; /* Magic value HID + CRC */
@@ -479,7 +479,7 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
ctx->joystick = joystick;
ctx->last_packet = SDL_GetTicks();
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -511,7 +511,7 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
ctx->is_bluetooth = SDL_TRUE;
/* Read a report to see if we're in enhanced mode */
size = hid_read_timeout(device->dev, data, sizeof(data), 16);
size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16);
#ifdef DEBUG_PS4_PROTOCOL
if (size > 0) {
HIDAPI_DumpPacket("PS4 first packet: size = %d", data, size);
@@ -598,10 +598,17 @@ HIDAPI_DriverPS4_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverPS4_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverPS4_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_TRUE;
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
Uint32 result = 0;
if (ctx->enhanced_mode && ctx->effects_supported) {
result |= SDL_JOYCAP_LED | SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -632,7 +639,7 @@ HIDAPI_DriverPS4_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joy
HIDAPI_DriverPS4_SetEnhancedMode(device, joystick);
}
SDL_zero(data);
SDL_zeroa(data);
if (ctx->is_bluetooth) {
data[0] = k_EPS4ReportIdBluetoothEffects;
@@ -684,7 +691,7 @@ HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti
}
static void
HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 920; /* This is noted as being 944 resolution, but 920 feels better */
@@ -846,7 +853,7 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_PS4_PROTOCOL
HIDAPI_DumpPacket("PS4 packet: size = %d", data, size);
#endif
@@ -908,7 +915,7 @@ HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -926,6 +933,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
{
SDL_HINT_JOYSTICK_HIDAPI_PS4,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverPS4_IsSupportedDevice,
HIDAPI_DriverPS4_GetDeviceName,
HIDAPI_DriverPS4_InitDevice,
@@ -935,7 +943,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
HIDAPI_DriverPS4_OpenJoystick,
HIDAPI_DriverPS4_RumbleJoystick,
HIDAPI_DriverPS4_RumbleJoystickTriggers,
HIDAPI_DriverPS4_HasJoystickLED,
HIDAPI_DriverPS4_GetJoystickCapabilities,
HIDAPI_DriverPS4_SetJoystickLED,
HIDAPI_DriverPS4_SendJoystickEffect,
HIDAPI_DriverPS4_SetJoystickSensorsEnabled,

View File

@@ -192,11 +192,11 @@ HIDAPI_DriverPS5_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return NULL;
}
static int ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
report[0] = report_id;
return hid_get_feature_report(dev, report, length);
return SDL_hid_get_feature_report(dev, report, length);
}
static void
@@ -471,7 +471,7 @@ HIDAPI_DriverPS5_TickleBluetooth(SDL_HIDAPI_Device *device)
/* This is just a dummy packet that should have no effect, since we don't set the CRC */
Uint8 data[78];
SDL_zero(data);
SDL_zeroa(data);
data[0] = k_EPS5ReportIdBluetoothEffects;
data[1] = 0x02; /* Magic value */
@@ -553,7 +553,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
ctx->joystick = joystick;
ctx->last_packet = SDL_GetTicks();
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -562,7 +562,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
device->context = ctx;
/* Read a report to see what mode we're in */
size = hid_read_timeout(device->dev, data, sizeof(data), 16);
size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16);
#ifdef DEBUG_PS5_PROTOCOL
if (size > 0) {
HIDAPI_DumpPacket("PS5 first packet: size = %d", data, size);
@@ -663,10 +663,17 @@ HIDAPI_DriverPS5_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverPS5_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverPS5_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_TRUE;
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
Uint32 result = 0;
if (ctx->enhanced_mode) {
result |= SDL_JOYCAP_LED | SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -696,7 +703,7 @@ HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joy
HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
}
SDL_zero(data);
SDL_zeroa(data);
if (ctx->is_bluetooth) {
data[0] = k_EPS5ReportIdBluetoothEffects;
@@ -761,7 +768,7 @@ HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti
}
static void
HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet)
HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet)
{
Sint16 axis;
@@ -855,7 +862,7 @@ HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev
}
static void
HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet)
HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 1070;
@@ -1010,7 +1017,7 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_PS5_PROTOCOL
HIDAPI_DumpPacket("PS5 packet: size = %d", data, size);
#endif
@@ -1071,7 +1078,7 @@ HIDAPI_DriverPS5_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1089,6 +1096,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
{
SDL_HINT_JOYSTICK_HIDAPI_PS5,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverPS5_IsSupportedDevice,
HIDAPI_DriverPS5_GetDeviceName,
HIDAPI_DriverPS5_InitDevice,
@@ -1098,7 +1106,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
HIDAPI_DriverPS5_OpenJoystick,
HIDAPI_DriverPS5_RumbleJoystick,
HIDAPI_DriverPS5_RumbleJoystickTriggers,
HIDAPI_DriverPS5_HasJoystickLED,
HIDAPI_DriverPS5_GetJoystickCapabilities,
HIDAPI_DriverPS5_SetJoystickLED,
HIDAPI_DriverPS5_SendJoystickEffect,
HIDAPI_DriverPS5_SetJoystickSensorsEnabled,

View File

@@ -80,7 +80,7 @@ static int SDL_HIDAPI_RumbleThread(void *data)
#ifdef DEBUG_RUMBLE
HIDAPI_DumpPacket("Rumble packet: size = %d", request->data, request->size);
#endif
hid_write(request->device->dev, request->data, request->size);
SDL_hid_write(request->device->dev, request->data, request->size);
}
SDL_UnlockMutex(request->device->dev_lock);
(void)SDL_AtomicDecRef(&request->device->rumble_pending);

View File

@@ -88,7 +88,7 @@ HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
SDL_free(ctx);
@@ -126,10 +126,10 @@ HIDAPI_DriverStadia_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joysti
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverStadia_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverStadia_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_FALSE;
return SDL_JOYCAP_RUMBLE;
}
static int
@@ -267,7 +267,7 @@ HIDAPI_DriverStadia_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_STADIA_PROTOCOL
HIDAPI_DumpPacket("Google Stadia packet: size = %d", data, size);
#endif
@@ -287,7 +287,7 @@ HIDAPI_DriverStadia_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
@@ -306,6 +306,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia =
{
SDL_HINT_JOYSTICK_HIDAPI_STADIA,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverStadia_IsSupportedDevice,
HIDAPI_DriverStadia_GetDeviceName,
HIDAPI_DriverStadia_InitDevice,
@@ -315,7 +316,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia =
HIDAPI_DriverStadia_OpenJoystick,
HIDAPI_DriverStadia_RumbleJoystick,
HIDAPI_DriverStadia_RumbleJoystickTriggers,
HIDAPI_DriverStadia_HasJoystickLED,
HIDAPI_DriverStadia_GetJoystickCapabilities,
HIDAPI_DriverStadia_SetJoystickLED,
HIDAPI_DriverStadia_SendJoystickEffect,
HIDAPI_DriverStadia_SetJoystickSensorsEnabled,

View File

@@ -190,7 +190,7 @@ typedef struct
// Wireless firmware quirk: the firmware intentionally signals "failure" when performing
// SET_FEATURE / GET_FEATURE when it actually means "pending radio round-trip". The only
// SET_FEATURE / GET_FEATURE when it actually means "pending radio roundtrip". The only
// way to make SET_FEATURE / GET_FEATURE work is to loop several times with a sleep. If
// it takes more than 50ms to get the response for SET_FEATURE / GET_FEATURE, we assume
// that the controller has failed.
@@ -220,7 +220,7 @@ static void hexdump( const uint8_t *ptr, int len )
static void ResetSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler )
{
memset( pAssembler->uBuffer, 0, sizeof( pAssembler->uBuffer ) );
SDL_memset( pAssembler->uBuffer, 0, sizeof( pAssembler->uBuffer ) );
pAssembler->nExpectedSegmentNumber = 0;
}
@@ -239,6 +239,9 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
{
if ( pAssembler->bIsBle )
{
uint8_t uSegmentHeader = pSegment[ 1 ];
int nSegmentNumber = uSegmentHeader & 0x07;
HEXDUMP( pSegment, nSegmentLength );
if ( pSegment[ 0 ] != BLE_REPORT_NUMBER )
@@ -255,7 +258,6 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
return -1;
}
uint8_t uSegmentHeader = pSegment[ 1 ];
DPRINTF("GOT PACKET HEADER = 0x%x\n", uSegmentHeader);
if ( ( uSegmentHeader & REPORT_SEGMENT_DATA_FLAG ) == 0 )
@@ -264,7 +266,6 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
return 0;
}
int nSegmentNumber = uSegmentHeader & 0x07;
if ( nSegmentNumber != pAssembler->nExpectedSegmentNumber )
{
ResetSteamControllerPacketAssembler( pAssembler );
@@ -278,7 +279,7 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
}
}
memcpy( pAssembler->uBuffer + nSegmentNumber * MAX_REPORT_SEGMENT_PAYLOAD_SIZE,
SDL_memcpy( pAssembler->uBuffer + nSegmentNumber * MAX_REPORT_SEGMENT_PAYLOAD_SIZE,
pSegment + 2, // ignore header and report number
MAX_REPORT_SEGMENT_PAYLOAD_SIZE );
@@ -293,7 +294,7 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
else
{
// Just pass through
memcpy( pAssembler->uBuffer,
SDL_memcpy( pAssembler->uBuffer,
pSegment,
nSegmentLength );
return nSegmentLength;
@@ -304,22 +305,23 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
#define BLE_MAX_READ_RETRIES 8
static int SetFeatureReport( hid_device *dev, unsigned char uBuffer[65], int nActualDataLen )
static int SetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65], int nActualDataLen )
{
DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
int nRet = -1;
bool bBle = true; // only wireless/BLE for now, though macOS could do wired in the future
DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
if ( bBle )
{
int nSegmentNumber = 0;
uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
unsigned char *pBufferPtr = uBuffer + 1;
if ( nActualDataLen < 1 )
return -1;
int nSegmentNumber = 0;
uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
// Skip report number in data
unsigned char *pBufferPtr = uBuffer + 1;
nActualDataLen--;
while ( nActualDataLen > 0 )
@@ -329,15 +331,15 @@ static int SetFeatureReport( hid_device *dev, unsigned char uBuffer[65], int nAc
nActualDataLen -= nBytesInPacket;
// Construct packet
memset( uPacketBuffer, 0, sizeof( uPacketBuffer ) );
SDL_memset( uPacketBuffer, 0, sizeof( uPacketBuffer ) );
uPacketBuffer[ 0 ] = BLE_REPORT_NUMBER;
uPacketBuffer[ 1 ] = GetSegmentHeader( nSegmentNumber, nActualDataLen == 0 );
memcpy( &uPacketBuffer[ 2 ], pBufferPtr, nBytesInPacket );
SDL_memcpy( &uPacketBuffer[ 2 ], pBufferPtr, nBytesInPacket );
pBufferPtr += nBytesInPacket;
nSegmentNumber++;
nRet = hid_send_feature_report( dev, uPacketBuffer, sizeof( uPacketBuffer ) );
nRet = SDL_hid_send_feature_report( dev, uPacketBuffer, sizeof( uPacketBuffer ) );
DPRINTF("SetFeatureReport() ret = %d\n", nRet);
}
}
@@ -345,24 +347,26 @@ static int SetFeatureReport( hid_device *dev, unsigned char uBuffer[65], int nAc
return nRet;
}
static int GetFeatureReport( hid_device *dev, unsigned char uBuffer[65] )
static int GetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65] )
{
DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer );
int nRet = -1;
bool bBle = true;
DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer );
if ( bBle )
{
int nRetries = 0;
uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE ];
SteamControllerPacketAssembler assembler;
InitializeSteamControllerPacketAssembler( &assembler );
int nRetries = 0;
uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE ];
while( nRetries < BLE_MAX_READ_RETRIES )
{
memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) );
SDL_memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) );
uSegmentBuffer[ 0 ] = BLE_REPORT_NUMBER;
nRet = hid_get_feature_report( dev, uSegmentBuffer, sizeof( uSegmentBuffer ) );
nRet = SDL_hid_get_feature_report( dev, uSegmentBuffer, sizeof( uSegmentBuffer ) );
DPRINTF( "GetFeatureReport ble ret=%d\n", nRet );
HEXDUMP( uSegmentBuffer, nRet );
@@ -382,7 +386,7 @@ static int GetFeatureReport( hid_device *dev, unsigned char uBuffer[65] )
{
// Leave space for "report number"
uBuffer[ 0 ] = 0;
memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
SDL_memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
return nPacketLength;
}
}
@@ -396,11 +400,12 @@ static int GetFeatureReport( hid_device *dev, unsigned char uBuffer[65] )
return nRet;
}
static int ReadResponse( hid_device *dev, uint8_t uBuffer[65], int nExpectedResponse )
static int ReadResponse( SDL_hid_device *dev, uint8_t uBuffer[65], int nExpectedResponse )
{
DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
int nRet = GetFeatureReport( dev, uBuffer );
DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
if ( nRet < 0 )
return nRet;
@@ -416,13 +421,18 @@ static int ReadResponse( hid_device *dev, uint8_t uBuffer[65], int nExpectedResp
//---------------------------------------------------------------------------
// Reset steam controller (unmap buttons and pads) and re-fetch capability bits
//---------------------------------------------------------------------------
static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
static bool ResetSteamController( SDL_hid_device *dev, bool bSuppressErrorSpew, uint32_t *punUpdateRateUS )
{
DPRINTF( "ResetSteamController hid=%p\n", dev );
// Firmware quirk: Set Feature and Get Feature requests always require a 65-byte buffer.
unsigned char buf[65];
int res = -1;
int res = -1, i;
int nSettings = 0;
int nAttributesLength;
FeatureReportMsg *msg;
uint32_t unUpdateRateUS = 9000; // Good default rate
DPRINTF( "ResetSteamController hid=%p\n", dev );
buf[0] = 0;
buf[1] = ID_GET_ATTRIBUTES_VALUES;
res = SetFeatureReport( dev, buf, 2 );
@@ -444,14 +454,40 @@ static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
return false;
}
int nAttributesLength = buf[ 2 ];
nAttributesLength = buf[ 2 ];
if ( nAttributesLength > res )
{
if ( !bSuppressErrorSpew )
printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
return false;
}
msg = (FeatureReportMsg *)&buf[1];
for ( i = 0; i < (int)msg->header.length / sizeof( ControllerAttribute ); ++i )
{
uint8_t unAttribute = msg->payload.getAttributes.attributes[i].attributeTag;
uint32_t unValue = msg->payload.getAttributes.attributes[i].attributeValue;
switch ( unAttribute )
{
case ATTRIB_UNIQUE_ID:
break;
case ATTRIB_PRODUCT_ID:
break;
case ATTRIB_CAPABILITIES:
break;
case ATTRIB_CONNECTION_INTERVAL_IN_US:
unUpdateRateUS = unValue;
break;
default:
break;
}
}
if ( punUpdateRateUS )
{
*punUpdateRateUS = unUpdateRateUS;
}
// Clear digital button mappings
buf[0] = 0;
buf[1] = ID_CLEAR_DIGITAL_MAPPINGS;
@@ -464,7 +500,7 @@ static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
}
// Reset the default settings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_LOAD_DEFAULT_SETTINGS;
buf[2] = 0;
res = SetFeatureReport( dev, buf, 3 );
@@ -476,14 +512,13 @@ static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
}
// Apply custom settings - clear trackpad modes (cancel mouse emulation), etc
int nSettings = 0;
#define ADD_SETTING(SETTING, VALUE) \
buf[3+nSettings*3] = SETTING; \
buf[3+nSettings*3+1] = ((uint16_t)VALUE)&0xFF; \
buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
++nSettings;
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_SETTINGS_VALUES;
ADD_SETTING( SETTING_WIRELESS_PACKET_VERSION, 2 );
ADD_SETTING( SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE );
@@ -512,7 +547,7 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
int iRetry;
for ( iRetry = 0; iRetry < 2; ++iRetry )
{
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_GET_DIGITAL_MAPPINGS;
buf[2] = 1; // one byte - requesting from index 0
buf[3] = 0;
@@ -545,7 +580,7 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
}
// Set our new mappings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_DIGITAL_MAPPINGS;
buf[2] = 6; // 2 settings x 3 bytes
buf[3] = IO_DIGITAL_BUTTON_RIGHT_TRIGGER;
@@ -571,36 +606,36 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
//---------------------------------------------------------------------------
// Read from a Steam Controller
//---------------------------------------------------------------------------
static int ReadSteamController( hid_device *dev, uint8_t *pData, int nDataSize )
static int ReadSteamController( SDL_hid_device *dev, uint8_t *pData, int nDataSize )
{
memset( pData, 0, nDataSize );
SDL_memset( pData, 0, nDataSize );
pData[ 0 ] = BLE_REPORT_NUMBER; // hid_read will also overwrite this with the same value, 0x03
return hid_read( dev, pData, nDataSize );
return SDL_hid_read( dev, pData, nDataSize );
}
//---------------------------------------------------------------------------
// Close a Steam Controller
//---------------------------------------------------------------------------
static void CloseSteamController( hid_device *dev )
static void CloseSteamController( SDL_hid_device *dev )
{
// Switch the Steam Controller back to lizard mode so it works with the OS
unsigned char buf[65];
int nSettings = 0;
// Reset digital button mappings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_DEFAULT_DIGITAL_MAPPINGS;
SetFeatureReport( dev, buf, 2 );
// Reset the default settings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_LOAD_DEFAULT_SETTINGS;
buf[2] = 0;
SetFeatureReport( dev, buf, 3 );
// Reset mouse mode for lizard mode
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_SETTINGS_VALUES;
ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE );
buf[2] = nSettings*3;
@@ -651,14 +686,23 @@ static void RotatePadShort( short *pX, short *pY, float flAngleInRad )
//---------------------------------------------------------------------------
static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState, ValveControllerStatePacket_t *pStatePacket )
{
memset(pState, 0, offsetof(SteamControllerStateInternal_t, sBatteryLevel));
int nLeftPadX;
int nLeftPadY;
int nRightPadX;
int nRightPadY;
int nPadOffset;
// 15 degrees in rad
const float flRotationAngle = 0.261799f;
SDL_memset(pState, 0, offsetof(SteamControllerStateInternal_t, sBatteryLevel));
//pState->eControllerType = m_eControllerType;
pState->eControllerType = 2; // k_eControllerType_SteamController;
pState->unPacketNum = pStatePacket->unPacketNum;
// We have a chunk of trigger data in the packet format here, so zero it out afterwards
memcpy(&pState->ulButtons, &pStatePacket->ButtonTriggerData.ulButtons, 8);
SDL_memcpy(&pState->ulButtons, &pStatePacket->ButtonTriggerData.ulButtons, 8);
pState->ulButtons &= ~0xFFFF000000LL;
// The firmware uses this bit to tell us what kind of data is packed into the left two axises
@@ -735,18 +779,14 @@ static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState,
pState->sRightPadX = pStatePacket->sRightPadX;
pState->sRightPadY = pStatePacket->sRightPadY;
int nLeftPadX = pState->sLeftPadX;
int nLeftPadY = pState->sLeftPadY;
int nRightPadX = pState->sRightPadX;
int nRightPadY = pState->sRightPadY;
// 15 degrees in rad
const float flRotationAngle = 0.261799f;
nLeftPadX = pState->sLeftPadX;
nLeftPadY = pState->sLeftPadY;
nRightPadX = pState->sRightPadX;
nRightPadY = pState->sRightPadY;
RotatePad(&nLeftPadX, &nLeftPadY, -flRotationAngle);
RotatePad(&nRightPadX, &nRightPadY, flRotationAngle);
int nPadOffset;
if (pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK)
nPadOffset = 1000;
else
@@ -782,7 +822,7 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
ucOptionDataMask |= (uint32_t)(*pData++) << 8;
if ( ucOptionDataMask & k_EBLEButtonChunk1 )
{
memcpy( &pState->ulButtons, pData, 3 );
SDL_memcpy( &pState->ulButtons, pData, 3 );
pData += 3;
}
if ( ucOptionDataMask & k_EBLEButtonChunk2 )
@@ -804,14 +844,14 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
// This doesn't handle any of the special headcrab stuff for raw joystick which is OK for now since that FW doesn't support
// this protocol yet either
int nLength = sizeof( pState->sLeftStickX ) + sizeof( pState->sLeftStickY );
memcpy( &pState->sLeftStickX, pData, nLength );
SDL_memcpy( &pState->sLeftStickX, pData, nLength );
pData += nLength;
}
if ( ucOptionDataMask & k_EBLELeftTrackpadChunk )
{
int nLength = sizeof( pState->sLeftPadX ) + sizeof( pState->sLeftPadY );
int nPadOffset;
memcpy( &pState->sLeftPadX, pData, nLength );
SDL_memcpy( &pState->sLeftPadX, pData, nLength );
if ( pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK )
nPadOffset = 1000;
else
@@ -827,7 +867,7 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
int nLength = sizeof( pState->sRightPadX ) + sizeof( pState->sRightPadY );
int nPadOffset = 0;
memcpy( &pState->sRightPadX, pData, nLength );
SDL_memcpy( &pState->sRightPadX, pData, nLength );
if ( pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK )
nPadOffset = 1000;
@@ -842,19 +882,19 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
if ( ucOptionDataMask & k_EBLEIMUAccelChunk )
{
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
memcpy( &pState->sAccelX, pData, nLength );
SDL_memcpy( &pState->sAccelX, pData, nLength );
pData += nLength;
}
if ( ucOptionDataMask & k_EBLEIMUGyroChunk )
{
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
memcpy( &pState->sGyroX, pData, nLength );
SDL_memcpy( &pState->sGyroX, pData, nLength );
pData += nLength;
}
if ( ucOptionDataMask & k_EBLEIMUQuatChunk )
{
int nLength = sizeof( pState->sGyroQuatW ) + sizeof( pState->sGyroQuatX ) + sizeof( pState->sGyroQuatY ) + sizeof( pState->sGyroQuatZ );
memcpy( &pState->sGyroQuatW, pData, nLength );
SDL_memcpy( &pState->sGyroQuatW, pData, nLength );
pData += nLength;
}
return true;
@@ -950,6 +990,7 @@ static bool UpdateSteamControllerState( const uint8_t *pData, int nDataSize, Ste
/*****************************************************************************************************/
typedef struct {
SDL_bool report_sensors;
SteamControllerPacketAssembler m_assembler;
SteamControllerStateInternal_t m_state;
SteamControllerStateInternal_t m_last_state;
@@ -989,6 +1030,8 @@ static SDL_bool
HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
SDL_DriverSteam_Context *ctx;
uint32_t update_rate_in_us = 0;
float update_rate_in_hz = 0.0f;
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
@@ -997,15 +1040,20 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
}
device->context = ctx;
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
goto error;
}
SDL_hid_set_nonblocking(device->dev, 1);
if (!ResetSteamController(device->dev, false)) {
if (!ResetSteamController(device->dev, false, &update_rate_in_us)) {
SDL_SetError("Couldn't reset controller");
goto error;
}
if (update_rate_in_us > 0) {
update_rate_in_hz = 1000000.0f / update_rate_in_us;
}
InitializeSteamControllerPacketAssembler(&ctx->m_assembler);
@@ -1013,13 +1061,16 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
joystick->nbuttons = 17;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz);
return SDL_TRUE;
error:
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
if (device->context) {
@@ -1044,11 +1095,11 @@ HIDAPI_DriverSteam_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystic
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverSteam_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverSteam_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* You should use the full Steam Input API for LED support */
return SDL_FALSE;
return 0;
}
static int
@@ -1067,8 +1118,25 @@ HIDAPI_DriverSteam_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *j
static int
HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
/* You should use the full Steam Input API for sensor support */
return SDL_Unsupported();
SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
unsigned char buf[65];
int nSettings = 0;
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_SETTINGS_VALUES;
if (enabled) {
ADD_SETTING( SETTING_GYRO_MODE, 0x18 /* SETTING_GYRO_SEND_RAW_ACCEL | SETTING_GYRO_MODE_SEND_RAW_GYRO */ );
} else {
ADD_SETTING( SETTING_GYRO_MODE, 0x00 /* SETTING_GYRO_MODE_OFF */ );
}
buf[2] = nSettings*3;
if (SetFeatureReport( device->dev, buf, 3+nSettings*3 ) < 0) {
return SDL_SetError("Couldn't write feature report");
}
ctx->report_sensors = enabled;
return 0;
}
static SDL_bool
@@ -1165,6 +1233,20 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, ctx->m_state.sRightPadX);
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~ctx->m_state.sRightPadY);
if (ctx->report_sensors) {
float values[3];
values[0] = (ctx->m_state.sGyroX / 32768.0f) * (2000.0f * (M_PI / 180.0f));
values[1] = (ctx->m_state.sGyroZ / 32768.0f) * (2000.0f * (M_PI / 180.0f));
values[2] = (ctx->m_state.sGyroY / 32768.0f) * (2000.0f * (M_PI / 180.0f));
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, values, 3);
values[0] = (ctx->m_state.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
values[1] = (ctx->m_state.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
values[2] = (-ctx->m_state.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, values, 3);
}
ctx->m_last_state = ctx->m_state;
}
@@ -1184,7 +1266,7 @@ HIDAPI_DriverSteam_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
{
CloseSteamController(device->dev);
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1202,6 +1284,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
{
SDL_HINT_JOYSTICK_HIDAPI_STEAM,
SDL_TRUE,
SDL_FALSE,
HIDAPI_DriverSteam_IsSupportedDevice,
HIDAPI_DriverSteam_GetDeviceName,
HIDAPI_DriverSteam_InitDevice,
@@ -1211,7 +1294,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
HIDAPI_DriverSteam_OpenJoystick,
HIDAPI_DriverSteam_RumbleJoystick,
HIDAPI_DriverSteam_RumbleJoystickTriggers,
HIDAPI_DriverSteam_HasJoystickLED,
HIDAPI_DriverSteam_GetJoystickCapabilities,
HIDAPI_DriverSteam_SetJoystickLED,
HIDAPI_DriverSteam_SendJoystickEffect,
HIDAPI_DriverSteam_SetSensorsEnabled,

View File

@@ -346,13 +346,13 @@ static int ReadInput(SDL_DriverSwitch_Context *ctx)
return 0;
}
return hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
return SDL_hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
}
static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int size)
{
#ifdef SWITCH_SYNCHRONOUS_WRITES
return hid_write(ctx->device->dev, data, size);
return SDL_hid_write(ctx->device->dev, data, size);
#else
/* Use the rumble thread for general asynchronous writes */
if (SDL_HIDAPI_LockRumble() < 0) {
@@ -418,7 +418,7 @@ static void ConstructSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommand
outPacket->commonData.ucPacketType = k_eSwitchOutputReportIDs_RumbleAndSubcommand;
outPacket->commonData.ucPacketNumber = ctx->m_nCommandNumber;
SDL_memcpy(&outPacket->commonData.rumbleData, &ctx->m_RumblePacket.rumbleData, sizeof(ctx->m_RumblePacket.rumbleData));
SDL_memcpy(outPacket->commonData.rumbleData, ctx->m_RumblePacket.rumbleData, sizeof(ctx->m_RumblePacket.rumbleData));
outPacket->ucSubcommandID = ucCommandID;
SDL_memcpy(outPacket->rgucSubcommandData, pBuf, ucLen);
@@ -621,7 +621,7 @@ static SDL_bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx)
ctx->m_eControllerType = (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType;
// Bytes 4-9: MAC address (big-endian)
memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
SDL_memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
return SDL_TRUE;
}
@@ -856,7 +856,7 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
ctx->device = device;
device->context = ctx;
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
goto error;
@@ -936,10 +936,13 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
/* Set the LED state */
if (ctx->m_bHasHomeLED) {
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, SDL_TRUE)) {
SetHomeLED(ctx, 100);
} else {
SetHomeLED(ctx, 0);
const char *hint = SDL_GetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED);
if (hint && *hint) {
if (SDL_GetStringBoolean(hint, SDL_TRUE)) {
SetHomeLED(ctx, 100);
} else {
SetHomeLED(ctx, 0);
}
}
}
SetSlotLED(ctx, (joystick->instance_id % 4));
@@ -983,7 +986,7 @@ error:
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
if (device->context) {
@@ -1103,11 +1106,18 @@ HIDAPI_DriverSwitch_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joysti
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverSwitch_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverSwitch_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
Uint32 result = 0;
if (!ctx->m_bInputOnly) {
/* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */
result |= SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -1527,7 +1537,7 @@ HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1545,6 +1555,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
{
SDL_HINT_JOYSTICK_HIDAPI_SWITCH,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverSwitch_IsSupportedDevice,
HIDAPI_DriverSwitch_GetDeviceName,
HIDAPI_DriverSwitch_InitDevice,
@@ -1554,7 +1565,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
HIDAPI_DriverSwitch_OpenJoystick,
HIDAPI_DriverSwitch_RumbleJoystick,
HIDAPI_DriverSwitch_RumbleJoystickTriggers,
HIDAPI_DriverSwitch_HasJoystickLED,
HIDAPI_DriverSwitch_GetJoystickCapabilities,
HIDAPI_DriverSwitch_SetJoystickLED,
HIDAPI_DriverSwitch_SendJoystickEffect,
HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,

View File

@@ -88,14 +88,14 @@ HIDAPI_DriverXbox360_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return NULL;
}
static SDL_bool SetSlotLED(hid_device *dev, Uint8 slot)
static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
{
const SDL_bool blink = SDL_FALSE;
Uint8 mode = (blink ? 0x02 : 0x06) + slot;
Uint8 led_packet[] = { 0x01, 0x03, 0x00 };
led_packet[2] = mode;
if (hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
if (SDL_hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
return SDL_FALSE;
}
return SDL_TRUE;
@@ -136,7 +136,7 @@ HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
SDL_free(ctx);
@@ -203,11 +203,11 @@ HIDAPI_DriverXbox360_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joyst
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverXbox360_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverXbox360_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
/* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */
return SDL_JOYCAP_RUMBLE;
}
static int
@@ -296,7 +296,7 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox 360 packet: size = %d", data, size);
#endif
@@ -318,7 +318,7 @@ HIDAPI_DriverXbox360_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
@@ -337,6 +337,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
{
SDL_HINT_JOYSTICK_HIDAPI_XBOX,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverXbox360_IsSupportedDevice,
HIDAPI_DriverXbox360_GetDeviceName,
HIDAPI_DriverXbox360_InitDevice,
@@ -346,7 +347,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
HIDAPI_DriverXbox360_OpenJoystick,
HIDAPI_DriverXbox360_RumbleJoystick,
HIDAPI_DriverXbox360_RumbleJoystickTriggers,
HIDAPI_DriverXbox360_HasJoystickLED,
HIDAPI_DriverXbox360_GetJoystickCapabilities,
HIDAPI_DriverXbox360_SetJoystickLED,
HIDAPI_DriverXbox360_SendJoystickEffect,
HIDAPI_DriverXbox360_SetJoystickSensorsEnabled,

View File

@@ -62,14 +62,14 @@ HIDAPI_DriverXbox360W_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return "Xbox 360 Wireless Controller";
}
static SDL_bool SetSlotLED(hid_device *dev, Uint8 slot)
static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
{
const SDL_bool blink = SDL_FALSE;
Uint8 mode = (blink ? 0x02 : 0x06) + slot;
Uint8 led_packet[] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
led_packet[3] = 0x40 + (mode % 0x0e);
if (hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
if (SDL_hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
return SDL_FALSE;
}
return SDL_TRUE;
@@ -105,7 +105,7 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -113,7 +113,7 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
if (hid_write(device->dev, init_packet, sizeof(init_packet)) != sizeof(init_packet)) {
if (SDL_hid_write(device->dev, init_packet, sizeof(init_packet)) != sizeof(init_packet)) {
SDL_SetError("Couldn't write init packet");
return SDL_FALSE;
}
@@ -173,11 +173,11 @@ HIDAPI_DriverXbox360W_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joys
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverXbox360W_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverXbox360W_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
/* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */
return SDL_JOYCAP_RUMBLE;
}
static int
@@ -199,7 +199,7 @@ HIDAPI_DriverXbox360W_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_J
}
static void
HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size)
HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size)
{
Sint16 axis;
const SDL_bool invert_y_axes = SDL_TRUE;
@@ -259,7 +259,7 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_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
@@ -321,7 +321,7 @@ HIDAPI_DriverXbox360W_FreeDevice(SDL_HIDAPI_Device *device)
{
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -334,6 +334,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W =
{
SDL_HINT_JOYSTICK_HIDAPI_XBOX,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverXbox360W_IsSupportedDevice,
HIDAPI_DriverXbox360W_GetDeviceName,
HIDAPI_DriverXbox360W_InitDevice,
@@ -343,7 +344,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W =
HIDAPI_DriverXbox360W_OpenJoystick,
HIDAPI_DriverXbox360W_RumbleJoystick,
HIDAPI_DriverXbox360W_RumbleJoystickTriggers,
HIDAPI_DriverXbox360W_HasJoystickLED,
HIDAPI_DriverXbox360W_GetJoystickCapabilities,
HIDAPI_DriverXbox360W_SetJoystickLED,
HIDAPI_DriverXbox360W_SendJoystickEffect,
HIDAPI_DriverXbox360W_SetJoystickSensorsEnabled,

View File

@@ -44,33 +44,23 @@
#define CONTROLLER_PREPARE_INPUT_TIMEOUT_MS 50
/* Connect controller */
/* Start controller */
static const Uint8 xboxone_init0[] = {
0x04, 0x20, 0x00, 0x00
};
/* Start controller - extended? */
static const Uint8 xboxone_init1[] = {
0x05, 0x20, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x55, 0x53, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
/* Start controller with input */
static const Uint8 xboxone_init2[] = {
0x05, 0x20, 0x03, 0x01, 0x00
};
/* Enable LED */
static const Uint8 xboxone_init3[] = {
static const Uint8 xboxone_init1[] = {
0x0A, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
};
/* Start input reports? */
static const Uint8 xboxone_init4[] = {
0x06, 0x20, 0x00, 0x02, 0x01, 0x00
};
/* Start rumble? */
static const Uint8 xboxone_init5[] = {
/* Setup rumble (not needed for Microsoft controllers, but it doesn't hurt) */
static const Uint8 xboxone_init2[] = {
0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
0x00, 0x00, 0xFF, 0x00, 0xEB
};
/* This controller passed security check */
static const Uint8 security_passed_packet[] = {
0x06, 0x20, 0x00, 0x02, 0x01, 0x00
};
/*
* This specifies the selection of init packets that a gamepad
@@ -90,16 +80,11 @@ typedef struct {
static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init0, sizeof(xboxone_init0), { 0x04, 0xb0 } },
/* The PDP Rock Candy controller doesn't start sending input until it gets this packet */
{ 0x0e6f, 0x0246, 0x0000, 0x0000, security_passed_packet, sizeof(security_passed_packet), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init0, sizeof(xboxone_init0), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init1, sizeof(xboxone_init1), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init2, sizeof(xboxone_init2), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init3, sizeof(xboxone_init3), { 0x00, 0x00 } },
/* These next packets are required for third party controllers (PowerA, PDP, HORI),
but aren't the correct protocol for Microsoft Xbox controllers.
*/
{ 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init4, sizeof(xboxone_init4), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init5, sizeof(xboxone_init5), { 0x00, 0x00 } },
};
typedef enum {
@@ -120,6 +105,7 @@ typedef struct {
Uint32 send_time;
Uint8 last_state[USB_PACKET_LENGTH];
SDL_bool has_guide_packet;
SDL_bool has_color_led;
SDL_bool has_paddles;
SDL_bool has_trigger_rumble;
SDL_bool has_share_button;
@@ -129,6 +115,12 @@ typedef struct {
Uint8 right_trigger_rumble;
} SDL_DriverXboxOne_Context;
static SDL_bool
ControllerHasColorLED(Uint16 vendor_id, Uint16 product_id)
{
return (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2);
}
static SDL_bool
ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
{
@@ -138,7 +130,7 @@ ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
static SDL_bool
ControllerHasTriggerRumble(Uint16 vendor_id, Uint16 product_id)
{
// All the Microsoft Xbox One controllers have trigger rumble
/* All the Microsoft Xbox One controllers have trigger rumble */
return (vendor_id == USB_VENDOR_MICROSOFT);
}
@@ -178,7 +170,10 @@ SendAckIfNeeded(SDL_HIDAPI_Device *device, Uint8 *data, int size)
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox One sending ACK packet: size = %d", ack_packet, sizeof(ack_packet));
#endif
hid_write(device->dev, ack_packet, sizeof(ack_packet));
if (SDL_HIDAPI_LockRumble() < 0 ||
SDL_HIDAPI_SendRumbleAndUnlock(device, ack_packet, sizeof(ack_packet)) != sizeof(ack_packet)) {
SDL_SetError("Couldn't send ack packet");
}
}
#endif /* __WIN32__ */
}
@@ -322,7 +317,7 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -335,6 +330,7 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
ctx->bluetooth = SDL_IsJoystickBluetoothXboxOne(device->vendor_id, device->product_id);
ctx->start_time = SDL_GetTicks();
ctx->sequence = 1;
ctx->has_color_led = ControllerHasColorLED(ctx->vendor_id, ctx->product_id);
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);
@@ -426,17 +422,44 @@ HIDAPI_DriverXboxOne_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joyst
return HIDAPI_DriverXboxOne_UpdateRumble(device);
}
static SDL_bool
HIDAPI_DriverXboxOne_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverXboxOne_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
Uint32 result = 0;
result |= SDL_JOYCAP_RUMBLE;
if (ctx->has_trigger_rumble) {
result |= SDL_JOYCAP_RUMBLE_TRIGGERS;
}
if (ctx->has_color_led) {
result |= SDL_JOYCAP_LED;
}
return result;
}
static int
HIDAPI_DriverXboxOne_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
if (ctx->has_color_led) {
Uint8 led_packet[] = { 0x0E, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
led_packet[5] = 0x00; /* Whiteness? Sets white intensity when RGB is 0, seems additive */
led_packet[6] = red;
led_packet[7] = green;
led_packet[8] = blue;
if (SDL_HIDAPI_SendRumble(device, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
return SDL_SetError("Couldn't send LED packet");
}
return 0;
} else {
return SDL_Unsupported();
}
}
static int
@@ -508,12 +531,16 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
Paddle bits:
P3: 0x01 (A) P1: 0x02 (B)
P4: 0x04 (X) P2: 0x08 (Y)
Xbox One Elite Series 2 report is 38 bytes, paddles in data[18], mode in data[19], mode 0 has no mapped paddles by default
Xbox One Elite Series 2 4.x firmware report is 38 bytes, paddles in data[18], mode in data[19], mode 0 has no mapped paddles by default
Paddle bits:
P3: 0x04 (A) P1: 0x01 (B)
P4: 0x08 (X) P2: 0x02 (Y)
Xbox One Elite Series 2 5.x firmware report is 50 bytes, paddles in data[22], mode in data[23], mode 0 has no mapped paddles by default
Paddle bits:
P3: 0x04 (A) P1: 0x01 (B)
P4: 0x08 (X) P2: 0x02 (Y)
*/
if (ctx->has_paddles && (size == 33 || size == 38)) {
if (ctx->has_paddles && (size == 33 || size == 38 || size == 50)) {
int paddle_index;
int button1_bit;
int button2_bit;
@@ -532,7 +559,7 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
/* The mapped controller state is at offset 4, the raw state is at offset 18, compare them to see if the paddles are mapped */
paddles_mapped = (SDL_memcmp(&data[4], &data[18], 2) != 0);
} else /* if (size == 38) */ {
} else if (size == 38) {
/* XBox One Elite Series 2 */
paddle_index = 18;
button1_bit = 0x01;
@@ -540,6 +567,15 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
button3_bit = 0x04;
button4_bit = 0x08;
paddles_mapped = (data[19] != 0);
} else /* if (size == 50) */{
/* XBox One Elite Series 2 */
paddle_index = 22;
button1_bit = 0x01;
button2_bit = 0x02;
button3_bit = 0x04;
button4_bit = 0x08;
paddles_mapped = (data[23] != 0);
}
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log(">>> Paddles: %d,%d,%d,%d mapped = %s\n",
@@ -595,6 +631,14 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
}
static void
HIDAPI_DriverXboxOne_HandleStatusPacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{
if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
}
}
static void
HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{
@@ -627,8 +671,10 @@ HIDAPI_DriverXboxOneBluetooth_HandleButtons16(SDL_Joystick *joystick, SDL_Driver
/*
* Xbox One S with firmware 4.8.1923 uses a 17 byte packet with BACK button in byte 16 and the GUIDE button in a separate packet (on Windows), or in byte 15 (on Linux)
* Xbox One S with firmware 5.x uses a 17 byte packet with BACK and GUIDE buttons in byte 15
* Xbox One Elite Series 2 with firmware 4.7.1872 uses a 55 byte packet with BACK button in byte 16, paddles starting at byte 33, and the GUIDE button in a separate packet
* Xbox One Elite Series 2 with firmware 4.8.1908 uses a 33 byte packet with BACK button in byte 16, paddles starting at byte 17, and the GUIDE button in a separate packet
* Xbox One Elite Series 2 with firmware 5.11.3112 uses a 19 byte packet with BACK and GUIDE buttons in byte 15
* Xbox Series X with firmware 5.5.2641 uses a 17 byte packet with BACK and GUIDE buttons in byte 15, and SHARE button in byte 17
*/
static void
@@ -644,10 +690,7 @@ HIDAPI_DriverXboxOneBluetooth_HandleButtons(SDL_Joystick *joystick, SDL_DriverXb
}
if (ctx->last_state[15] != data[15]) {
if (ctx->has_share_button) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[15] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[15] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
} else if (!ctx->has_guide_packet) {
if (!ctx->has_guide_packet) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[15] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
}
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
@@ -655,12 +698,11 @@ HIDAPI_DriverXboxOneBluetooth_HandleButtons(SDL_Joystick *joystick, SDL_DriverXb
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[16] != data[16]) {
if (ctx->has_share_button) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
} else {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->has_share_button) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[15] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
} else {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, ((data[15] & 0x04) || (data[16] & 0x01)) ? SDL_PRESSED : SDL_RELEASED);
}
/*
@@ -727,8 +769,13 @@ HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, SDL_Driv
if (size == 16) {
/* Original Xbox One S, with separate report for guide button */
HIDAPI_DriverXboxOneBluetooth_HandleButtons16(joystick, ctx, data, size);
} else {
} else if (size > 16) {
HIDAPI_DriverXboxOneBluetooth_HandleButtons(joystick, ctx, data, size);
} else {
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log("Unknown Bluetooth state packet format\n");
#endif
return;
}
if (ctx->last_state[13] != data[13]) {
@@ -908,7 +955,7 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
Uint8 data[USB_PACKET_LENGTH];
int size;
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox One packet: size = %d", data, size);
#endif
@@ -961,16 +1008,18 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
is firmware version 5.5.2641.0, and product version 0x0505 = 1285
then 8 bytes of unknown data
*/
if (data[1] == 0x20) {
#ifdef DEBUG_JOYSTICK
SDL_Log("Controller announce after %u ms\n", (SDL_GetTicks() - ctx->start_time));
SDL_Log("Controller announce after %u ms\n", (SDL_GetTicks() - ctx->start_time));
#endif
SetInitState(ctx, XBOX_ONE_INIT_STATE_START_NEGOTIATING);
SetInitState(ctx, XBOX_ONE_INIT_STATE_START_NEGOTIATING);
} else {
/* Possibly an announce from a device plugged into the controller */
}
break;
case 0x03:
/* Controller heartbeat */
if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
}
/* Controller status update */
HIDAPI_DriverXboxOne_HandleStatusPacket(joystick, ctx, data, size);
break;
case 0x04:
/* Unknown chatty controller information, sent by both sides */
@@ -1060,7 +1109,7 @@ HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
{
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1078,6 +1127,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
{
SDL_HINT_JOYSTICK_HIDAPI_XBOX,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverXboxOne_IsSupportedDevice,
HIDAPI_DriverXboxOne_GetDeviceName,
HIDAPI_DriverXboxOne_InitDevice,
@@ -1087,7 +1137,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
HIDAPI_DriverXboxOne_OpenJoystick,
HIDAPI_DriverXboxOne_RumbleJoystick,
HIDAPI_DriverXboxOne_RumbleJoystickTriggers,
HIDAPI_DriverXboxOne_HasJoystickLED,
HIDAPI_DriverXboxOne_GetJoystickCapabilities,
HIDAPI_DriverXboxOne_SetJoystickLED,
HIDAPI_DriverXboxOne_SendJoystickEffect,
HIDAPI_DriverXboxOne_SetJoystickSensorsEnabled,

View File

@@ -25,52 +25,17 @@
#include "SDL_atomic.h"
#include "SDL_endian.h"
#include "SDL_hints.h"
#include "SDL_thread.h"
#include "SDL_timer.h"
#include "SDL_joystick.h"
#include "SDL_log.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
#include "../../SDL_hints_c.h"
#if defined(__WIN32__)
#include "../../core/windows/SDL_windows.h"
#include "../windows/SDL_rawinputjoystick_c.h"
#endif
#if defined(__MACOSX__)
#include <CoreFoundation/CoreFoundation.h>
#include <mach/mach.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDDevice.h>
#include <IOKit/usb/USBSpec.h>
#endif
#ifdef SDL_USE_LIBUDEV
#include "../../core/linux/SDL_udev.h"
#include <poll.h>
#include <unistd.h>
#endif
#ifdef HAVE_INOTIFY
#include <unistd.h> /* just in case we didn't use that SDL_USE_LIBUDEV block... */
#include <errno.h> /* errno, strerror */
#include <fcntl.h>
#include <limits.h> /* For the definition of NAME_MAX */
#include <sys/inotify.h>
#endif
#if defined(SDL_USE_LIBUDEV)
typedef enum
{
ENUMERATION_UNSET,
ENUMERATION_LIBUDEV,
ENUMERATION_FALLBACK
} LinuxEnumerationMethod;
static LinuxEnumerationMethod linux_enumeration_method = ENUMERATION_UNSET;
#endif
struct joystick_hwdata
{
@@ -109,434 +74,12 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
};
static int SDL_HIDAPI_numdrivers = 0;
static SDL_SpinLock SDL_HIDAPI_spinlock;
static Uint32 SDL_HIDAPI_change_count = 0;
static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
static int SDL_HIDAPI_numjoysticks = 0;
static SDL_bool initialized = SDL_FALSE;
static SDL_bool shutting_down = SDL_FALSE;
#if defined(HAVE_INOTIFY)
static int inotify_fd = -1;
#endif
#if defined(SDL_USE_LIBUDEV)
static const SDL_UDEV_Symbols * usyms = NULL;
#endif
static struct
{
SDL_bool m_bHaveDevicesChanged;
SDL_bool m_bCanGetNotifications;
Uint32 m_unLastDetect;
#if defined(__WIN32__)
SDL_threadID m_nThreadID;
WNDCLASSEXA m_wndClass;
HWND m_hwndMsg;
HDEVNOTIFY m_hNotify;
double m_flLastWin32MessageCheck;
#endif
#if defined(__MACOSX__)
IONotificationPortRef m_notificationPort;
mach_port_t m_notificationMach;
#endif
#if defined(SDL_USE_LIBUDEV)
struct udev *m_pUdev;
struct udev_monitor *m_pUdevMonitor;
int m_nUdevFd;
#endif
} SDL_HIDAPI_discovery;
#ifdef __WIN32__
struct _DEV_BROADCAST_HDR
{
DWORD dbch_size;
DWORD dbch_devicetype;
DWORD dbch_reserved;
};
typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A
{
DWORD dbcc_size;
DWORD dbcc_devicetype;
DWORD dbcc_reserved;
GUID dbcc_classguid;
char dbcc_name[ 1 ];
} DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;
typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR;
#define DBT_DEVICEARRIVAL 0x8000 /* system detected a new device */
#define DBT_DEVICEREMOVECOMPLETE 0x8004 /* device was removed from the system */
#define DBT_DEVTYP_DEVICEINTERFACE 0x00000005 /* device interface class */
#define DBT_DEVNODES_CHANGED 0x0007
#define DBT_CONFIGCHANGED 0x0018
#define DBT_DEVICETYPESPECIFIC 0x8005 /* type specific event */
#define DBT_DEVINSTSTARTED 0x8008 /* device installed and started */
#include <initguid.h>
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
static LRESULT CALLBACK ControllerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_DEVICECHANGE:
switch (wParam) {
case DBT_DEVICEARRIVAL:
case DBT_DEVICEREMOVECOMPLETE:
if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
}
break;
}
return TRUE;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
#endif /* __WIN32__ */
#if defined(__MACOSX__)
static void CallbackIOServiceFunc(void *context, io_iterator_t portIterator)
{
/* Must drain the iterator, or we won't receive new notifications */
io_object_t entry;
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
*(SDL_bool*)context = SDL_TRUE;
}
}
#endif /* __MACOSX__ */
#ifdef HAVE_INOTIFY
#ifdef HAVE_INOTIFY_INIT1
static int SDL_inotify_init1(void) {
return inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
}
#else
static int SDL_inotify_init1(void) {
int fd = inotify_init();
if (fd < 0) return -1;
fcntl(fd, F_SETFL, O_NONBLOCK);
fcntl(fd, F_SETFD, FD_CLOEXEC);
return fd;
}
#endif
static int
StrHasPrefix(const char *string, const char *prefix)
{
return (SDL_strncmp(string, prefix, SDL_strlen(prefix)) == 0);
}
static int
StrIsInteger(const char *string)
{
const char *p;
if (*string == '\0') {
return 0;
}
for (p = string; *p != '\0'; p++) {
if (*p < '0' || *p > '9') {
return 0;
}
}
return 1;
}
#endif
static void
HIDAPI_InitializeDiscovery()
{
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_FALSE;
SDL_HIDAPI_discovery.m_unLastDetect = 0;
#if defined(__WIN32__)
SDL_HIDAPI_discovery.m_nThreadID = SDL_ThreadID();
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 */
SDL_HIDAPI_discovery.m_wndClass.cbSize = sizeof(WNDCLASSEX);
RegisterClassExA(&SDL_HIDAPI_discovery.m_wndClass);
SDL_HIDAPI_discovery.m_hwndMsg = CreateWindowExA(0, "SDL_HIDAPI_DEVICE_DETECTION", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
{
DEV_BROADCAST_DEVICEINTERFACE_A devBroadcast;
SDL_zero(devBroadcast);
devBroadcast.dbcc_size = sizeof( devBroadcast );
devBroadcast.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
devBroadcast.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
/* DEVICE_NOTIFY_ALL_INTERFACE_CLASSES is important, makes GUID_DEVINTERFACE_USB_DEVICE ignored,
* but that seems to be necessary to get a notice after each individual usb input device actually
* installs, rather than just as the composite device is seen.
*/
SDL_HIDAPI_discovery.m_hNotify = RegisterDeviceNotification( SDL_HIDAPI_discovery.m_hwndMsg, &devBroadcast, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES );
SDL_HIDAPI_discovery.m_bCanGetNotifications = ( SDL_HIDAPI_discovery.m_hNotify != 0 );
}
#endif /* __WIN32__ */
#if defined(__MACOSX__)
SDL_HIDAPI_discovery.m_notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
if (SDL_HIDAPI_discovery.m_notificationPort) {
{
io_iterator_t portIterator = 0;
io_object_t entry;
IOReturn result = IOServiceAddMatchingNotification(
SDL_HIDAPI_discovery.m_notificationPort,
kIOFirstMatchNotification,
IOServiceMatching(kIOHIDDeviceKey),
CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
if (result == 0) {
/* Must drain the existing iterator, or we won't receive new notifications */
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
}
} else {
IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
SDL_HIDAPI_discovery.m_notificationPort = nil;
}
}
{
io_iterator_t portIterator = 0;
io_object_t entry;
IOReturn result = IOServiceAddMatchingNotification(
SDL_HIDAPI_discovery.m_notificationPort,
kIOTerminatedNotification,
IOServiceMatching(kIOHIDDeviceKey),
CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
if (result == 0) {
/* Must drain the existing iterator, or we won't receive new notifications */
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
}
} else {
IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
SDL_HIDAPI_discovery.m_notificationPort = nil;
}
}
}
SDL_HIDAPI_discovery.m_notificationMach = MACH_PORT_NULL;
if (SDL_HIDAPI_discovery.m_notificationPort) {
SDL_HIDAPI_discovery.m_notificationMach = IONotificationPortGetMachPort(SDL_HIDAPI_discovery.m_notificationPort);
}
SDL_HIDAPI_discovery.m_bCanGetNotifications = (SDL_HIDAPI_discovery.m_notificationMach != MACH_PORT_NULL);
#endif // __MACOSX__
#if defined(SDL_USE_LIBUDEV)
if (linux_enumeration_method == ENUMERATION_LIBUDEV) {
SDL_HIDAPI_discovery.m_pUdev = NULL;
SDL_HIDAPI_discovery.m_pUdevMonitor = NULL;
SDL_HIDAPI_discovery.m_nUdevFd = -1;
usyms = SDL_UDEV_GetUdevSyms();
if (usyms) {
SDL_HIDAPI_discovery.m_pUdev = usyms->udev_new();
}
if (SDL_HIDAPI_discovery.m_pUdev) {
SDL_HIDAPI_discovery.m_pUdevMonitor = usyms->udev_monitor_new_from_netlink(SDL_HIDAPI_discovery.m_pUdev, "udev");
if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
usyms->udev_monitor_enable_receiving(SDL_HIDAPI_discovery.m_pUdevMonitor);
SDL_HIDAPI_discovery.m_nUdevFd = usyms->udev_monitor_get_fd(SDL_HIDAPI_discovery.m_pUdevMonitor);
SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_TRUE;
}
}
}
else
#endif /* SDL_USE_LIBUDEV */
{
#if defined(HAVE_INOTIFY)
inotify_fd = SDL_inotify_init1();
if (inotify_fd < 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
"Unable to initialize inotify, falling back to polling: %s",
strerror(errno));
return;
}
/* We need to watch for attribute changes in addition to
* creation, because when a device is first created, it has
* permissions that we can't read. When udev chmods it to
* something that we maybe *can* read, we'll get an
* IN_ATTRIB event to tell us. */
if (inotify_add_watch(inotify_fd, "/dev",
IN_CREATE | IN_DELETE | IN_MOVE | IN_ATTRIB) < 0) {
close(inotify_fd);
inotify_fd = -1;
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
"Unable to add inotify watch, falling back to polling: %s",
strerror (errno));
return;
}
SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_TRUE;
#endif /* HAVE_INOTIFY */
}
}
static void
HIDAPI_UpdateDiscovery()
{
if (!SDL_HIDAPI_discovery.m_bCanGetNotifications) {
const Uint32 SDL_HIDAPI_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
Uint32 now = SDL_GetTicks();
if (!SDL_HIDAPI_discovery.m_unLastDetect || SDL_TICKS_PASSED(now, SDL_HIDAPI_discovery.m_unLastDetect + SDL_HIDAPI_DETECT_INTERVAL_MS)) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
SDL_HIDAPI_discovery.m_unLastDetect = now;
}
return;
}
#if defined(__WIN32__)
#if 0 /* just let the usual SDL_PumpEvents loop dispatch these, fixing bug 4286. --ryan. */
/* We'll only get messages on the same thread that created the window */
if (SDL_ThreadID() == SDL_HIDAPI_discovery.m_nThreadID) {
MSG msg;
while (PeekMessage(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0, PM_NOREMOVE)) {
if (GetMessageA(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0) != 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
#endif
#endif /* __WIN32__ */
#if defined(__MACOSX__)
if (SDL_HIDAPI_discovery.m_notificationPort) {
struct { mach_msg_header_t hdr; char payload[ 4096 ]; } msg;
while (mach_msg(&msg.hdr, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, sizeof(msg), SDL_HIDAPI_discovery.m_notificationMach, 0, MACH_PORT_NULL) == KERN_SUCCESS) {
IODispatchCalloutFromMessage(NULL, &msg.hdr, SDL_HIDAPI_discovery.m_notificationPort);
}
}
#endif
#if defined(SDL_USE_LIBUDEV)
if (linux_enumeration_method == ENUMERATION_LIBUDEV) {
if (SDL_HIDAPI_discovery.m_nUdevFd >= 0) {
/* Drain all notification events.
* We don't expect a lot of device notifications so just
* do a new discovery on any kind or number of notifications.
* This could be made more restrictive if necessary.
*/
for (;;) {
struct pollfd PollUdev;
struct udev_device *pUdevDevice;
PollUdev.fd = SDL_HIDAPI_discovery.m_nUdevFd;
PollUdev.events = POLLIN;
if (poll(&PollUdev, 1, 0) != 1) {
break;
}
pUdevDevice = usyms->udev_monitor_receive_device(SDL_HIDAPI_discovery.m_pUdevMonitor);
if (pUdevDevice) {
const char *action = NULL;
action = usyms->udev_device_get_action(pUdevDevice);
if (!action || SDL_strcmp(action, "add") == 0 || SDL_strcmp(action, "remove") == 0) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
}
usyms->udev_device_unref(pUdevDevice);
}
}
}
}
else
#endif /* SDL_USE_LIBUDEV */
{
#if defined(HAVE_INOTIFY)
if (inotify_fd >= 0) {
union
{
struct inotify_event event;
char storage[4096];
char enough_for_inotify[sizeof (struct inotify_event) + NAME_MAX + 1];
} buf;
ssize_t bytes;
size_t remain = 0;
size_t len;
bytes = read(inotify_fd, &buf, sizeof (buf));
if (bytes > 0) {
remain = (size_t) bytes;
}
while (remain > 0) {
if (buf.event.len > 0 &&
!SDL_HIDAPI_discovery.m_bHaveDevicesChanged) {
if (StrHasPrefix(buf.event.name, "hidraw") &&
StrIsInteger(buf.event.name + strlen ("hidraw"))) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
/* We found an hidraw change. We still continue to
* drain the inotify fd to avoid leaving old
* notifications in the queue. */
}
}
len = sizeof (struct inotify_event) + buf.event.len;
remain -= len;
if (remain != 0) {
memmove(&buf.storage[0], &buf.storage[len], remain);
}
}
}
#endif /* HAVE_INOTIFY */
}
}
static void
HIDAPI_ShutdownDiscovery()
{
#if defined(__WIN32__)
if (SDL_HIDAPI_discovery.m_hNotify)
UnregisterDeviceNotification(SDL_HIDAPI_discovery.m_hNotify);
if (SDL_HIDAPI_discovery.m_hwndMsg) {
DestroyWindow(SDL_HIDAPI_discovery.m_hwndMsg);
}
UnregisterClassA(SDL_HIDAPI_discovery.m_wndClass.lpszClassName, SDL_HIDAPI_discovery.m_wndClass.hInstance);
#endif
#if defined(__MACOSX__)
if (SDL_HIDAPI_discovery.m_notificationPort) {
IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
}
#endif
#if defined(SDL_USE_LIBUDEV)
if (linux_enumeration_method == ENUMERATION_LIBUDEV &&
usyms) {
if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
usyms->udev_monitor_unref(SDL_HIDAPI_discovery.m_pUdevMonitor);
}
if (SDL_HIDAPI_discovery.m_pUdev) {
usyms->udev_unref(SDL_HIDAPI_discovery.m_pUdev);
}
SDL_UDEV_ReleaseUdevSyms();
usyms = NULL;
}
#endif
}
void
HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size)
{
@@ -658,8 +201,7 @@ static void
HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
{
if (device->driver) {
/* Already setup */
return;
return; /* Already setup */
}
device->driver = HIDAPI_GetDeviceDriver(device);
@@ -681,8 +223,7 @@ static void
HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
{
if (!device->driver) {
/* Already cleaned up */
return;
return; /* Already cleaned up */
}
/* Disconnect any joysticks */
@@ -767,17 +308,7 @@ HIDAPI_JoystickInit(void)
}
#endif
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__TVOS__)
/* The hidapi framwork is weak-linked on Apple platforms */
int HID_API_EXPORT HID_API_CALL hid_init(void) __attribute__((weak_import));
if (hid_init == NULL) {
SDL_SetError("Couldn't initialize hidapi, framework not available");
return -1;
}
#endif /* __MACOSX__ || __IPHONEOS__ || __TVOS__ */
if (hid_init() < 0) {
if (SDL_hid_init() < 0) {
SDL_SetError("Couldn't initialize hidapi");
return -1;
}
@@ -788,7 +319,6 @@ HIDAPI_JoystickInit(void)
}
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
SDL_HIDAPIDriverHintChanged, NULL);
HIDAPI_InitializeDiscovery();
HIDAPI_JoystickDetect();
HIDAPI_UpdateDevices();
@@ -863,10 +393,13 @@ HIDAPI_ConvertString(const wchar_t *wide_string)
if (wide_string) {
string = SDL_iconv_string("UTF-8", "WCHAR_T", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
if (!string) {
if (sizeof(wchar_t) == sizeof(Uint16)) {
switch (sizeof(wchar_t)) {
case 2:
string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
} else if (sizeof(wchar_t) == sizeof(Uint32)) {
break;
case 4:
string = SDL_iconv_string("UTF-8", "UCS-4-INTERNAL", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
break;
}
}
}
@@ -874,7 +407,7 @@ HIDAPI_ConvertString(const wchar_t *wide_string)
}
static void
HIDAPI_AddDevice(struct hid_device_info *info)
HIDAPI_AddDevice(struct SDL_hid_device_info *info)
{
SDL_HIDAPI_Device *device;
SDL_HIDAPI_Device *curr, *last = NULL;
@@ -1038,7 +571,7 @@ static void
HIDAPI_UpdateDeviceList(void)
{
SDL_HIDAPI_Device *device;
struct hid_device_info *devs, *info;
struct SDL_hid_device_info *devs, *info;
SDL_LockJoysticks();
@@ -1051,7 +584,7 @@ HIDAPI_UpdateDeviceList(void)
/* Enumerate the devices */
if (SDL_HIDAPI_numdrivers > 0) {
devs = hid_enumerate(0, 0);
devs = SDL_hid_enumerate(0, 0);
if (devs) {
for (info = devs; info; info = info->next) {
device = HIDAPI_GetJoystickByInfo(info->path, info->vendor_id, info->product_id);
@@ -1061,7 +594,7 @@ HIDAPI_UpdateDeviceList(void)
HIDAPI_AddDevice(info);
}
}
hid_free_enumeration(devs);
SDL_hid_free_enumeration(devs);
}
}
@@ -1202,11 +735,10 @@ static void
HIDAPI_JoystickDetect(void)
{
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
HIDAPI_UpdateDiscovery();
if (SDL_HIDAPI_discovery.m_bHaveDevicesChanged) {
/* FIXME: We probably need to schedule an update in a few seconds as well */
Uint32 count = SDL_hid_device_change_count();
if (SDL_HIDAPI_change_count != count) {
HIDAPI_UpdateDeviceList();
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_FALSE;
SDL_HIDAPI_change_count = count;
}
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
}
@@ -1363,15 +895,15 @@ HIDAPI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16
return result;
}
static SDL_bool
HIDAPI_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
HIDAPI_JoystickGetCapabilities(SDL_Joystick *joystick)
{
SDL_bool result = SDL_FALSE;
Uint32 result = 0;
if (joystick->hwdata) {
SDL_HIDAPI_Device *device = joystick->hwdata->device;
result = device->driver->HasJoystickLED(device, joystick);
result = device->driver->GetJoystickCapabilities(device, joystick);
}
return result;
@@ -1470,17 +1002,8 @@ HIDAPI_JoystickQuit(void)
shutting_down = SDL_TRUE;
HIDAPI_ShutdownDiscovery();
SDL_HIDAPI_QuitRumble();
#if defined(HAVE_INOTIFY)
if (inotify_fd >= 0) {
close(inotify_fd);
inotify_fd = -1;
}
#endif
while (SDL_HIDAPI_devices) {
HIDAPI_DelDevice(SDL_HIDAPI_devices);
}
@@ -1495,7 +1018,7 @@ HIDAPI_JoystickQuit(void)
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
SDL_HIDAPIDriverHintChanged, NULL);
hid_exit();
SDL_hid_exit();
shutting_down = SDL_FALSE;
initialized = SDL_FALSE;
@@ -1520,7 +1043,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
HIDAPI_JoystickOpen,
HIDAPI_JoystickRumble,
HIDAPI_JoystickRumbleTriggers,
HIDAPI_JoystickHasLED,
HIDAPI_JoystickGetCapabilities,
HIDAPI_JoystickSetLED,
HIDAPI_JoystickSendEffect,
HIDAPI_JoystickSetSensorsEnabled,

View File

@@ -27,7 +27,7 @@
#include "SDL_mutex.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
#include "../../hidapi/hidapi/hidapi.h"
#include "SDL_hidapi.h"
#include "../usb_ids.h"
/* This is the full set of HIDAPI drivers available */
@@ -70,7 +70,7 @@ typedef struct _SDL_HIDAPI_Device
struct _SDL_HIDAPI_DeviceDriver *driver;
void *context;
SDL_mutex *dev_lock;
hid_device *dev;
SDL_hid_device *dev;
SDL_atomic_t rumble_pending;
int num_joysticks;
SDL_JoystickID *joysticks;
@@ -88,6 +88,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
{
const char *hint;
SDL_bool enabled;
SDL_bool enabled_default;
SDL_bool (*IsSupportedDevice)(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id);
SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device);
@@ -97,7 +98,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
SDL_bool (*OpenJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
int (*RumbleJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
int (*RumbleJoystickTriggers)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble);
SDL_bool (*HasJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
Uint32 (*GetJoystickCapabilities)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
int (*SetJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
int (*SendJoystickEffect)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size);
int (*SetJoystickSensorsEnabled)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled);

View File

@@ -23,6 +23,43 @@
#pragma pack(1)
#define HID_FEATURE_REPORT_BYTES 64
// Header for all host <==> target messages
typedef struct
{
unsigned char type;
unsigned char length;
} FeatureReportHeader;
// Generic controller attribute structure
typedef struct
{
unsigned char attributeTag;
uint32_t attributeValue;
} ControllerAttribute;
// Generic controller settings structure
typedef struct
{
ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ];
} MsgGetAttributes;
// This is the only message struct that application code should use to interact with feature request messages. Any new
// messages should be added to the union. The structures defined here should correspond to the ones defined in
// ValveDeviceCore.cpp.
//
typedef struct
{
FeatureReportHeader header;
union
{
MsgGetAttributes getAttributes;
} payload;
} FeatureReportMsg;
// Roll this version forward anytime that you are breaking compatibility of existing
// message types within ValveInReport_t or the header itself. Hopefully this should
// be super rare and instead you shoudl just add new message payloads to the union,

View File

@@ -298,10 +298,10 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle
subtype = 1;
} else if (device->has_xbox_share_button) {
/* Assume Xbox Series X Controller unless/until GCController flows VID/PID */
product = USB_PRODUCT_XBOX_SERIES_X_BLUETOOTH;
product = USB_PRODUCT_XBOX_SERIES_X_BLE;
subtype = 1;
} else {
/* Assume Xbox One S BLE Controller unless/until GCController flows VID/PID */
/* Assume Xbox One S Bluetooth Controller unless/until GCController flows VID/PID */
product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH;
subtype = 0;
}
@@ -652,7 +652,7 @@ IOS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
}
static SDL_JoystickGUID
IOS_JoystickGetDeviceGUID( int device_index )
IOS_JoystickGetDeviceGUID(int device_index)
{
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
SDL_JoystickGUID guid;
@@ -783,9 +783,9 @@ IOS_AccelerometerUpdate(SDL_Joystick *joystick)
*/
/* clamp the data */
accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
accel.x = SDL_clamp(accel.x, -maxgforce, maxgforce);
accel.y = SDL_clamp(accel.y, -maxgforce, maxgforce);
accel.z = SDL_clamp(accel.z, -maxgforce, maxgforce);
/* pass in data mapped to range of SInt16 */
SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
@@ -1085,13 +1085,17 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
-(void)cleanup
{
if (self.player != nil) {
[self.player cancelAndReturnError:nil];
self.player = nil;
}
if (self.engine != nil) {
[self.engine stopWithCompletionHandler:nil];
self.engine = nil;
@autoreleasepool {
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (self.player != nil) {
[self.player cancelAndReturnError:nil];
self.player = nil;
}
if (self.engine != nil) {
[self.engine stopWithCompletionHandler:nil];
self.engine = nil;
}
}
}
}
@@ -1268,6 +1272,10 @@ IOS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 h
#ifdef ENABLE_MFI_RUMBLE
SDL_JoystickDeviceItem *device = joystick->hwdata;
if (device == NULL) {
return SDL_SetError("Controller is no longer connected");
}
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (!device->rumble && device->controller && device->controller.haptics) {
SDL_RumbleContext *rumble = IOS_JoystickInitRumble(device->controller);
@@ -1294,6 +1302,10 @@ IOS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 ri
#ifdef ENABLE_MFI_RUMBLE
SDL_JoystickDeviceItem *device = joystick->hwdata;
if (device == NULL) {
return SDL_SetError("Controller is no longer connected");
}
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (!device->rumble && device->controller && device->controller.haptics) {
SDL_RumbleContext *rumble = IOS_JoystickInitRumble(device->controller);
@@ -1314,22 +1326,43 @@ IOS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 ri
#endif
}
static SDL_bool
IOS_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
IOS_JoystickGetCapabilities(SDL_Joystick *joystick)
{
#ifdef ENABLE_MFI_LIGHT
Uint32 result = 0;
#if defined(ENABLE_MFI_LIGHT) || defined(ENABLE_MFI_RUMBLE)
@autoreleasepool {
SDL_JoystickDeviceItem *device = joystick->hwdata;
if (device == NULL) {
return 0;
}
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
GCDeviceLight *light = controller.light;
if (light) {
return SDL_TRUE;
GCController *controller = device->controller;
#ifdef ENABLE_MFI_LIGHT
if (controller.light) {
result |= SDL_JOYCAP_LED;
}
#endif
#ifdef ENABLE_MFI_RUMBLE
if (controller.haptics) {
for (GCHapticsLocality locality in controller.haptics.supportedLocalities) {
if ([locality isEqualToString:GCHapticsLocalityHandles]) {
result |= SDL_JOYCAP_RUMBLE;
} else if ([locality isEqualToString:GCHapticsLocalityTriggers]) {
result |= SDL_JOYCAP_RUMBLE_TRIGGERS;
}
}
}
#endif
}
}
#endif /* ENABLE_MFI_LIGHT */
#endif /* ENABLE_MFI_LIGHT || ENABLE_MFI_RUMBLE */
return SDL_FALSE;
return result;
}
static int
@@ -1337,8 +1370,14 @@ IOS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
#ifdef ENABLE_MFI_LIGHT
@autoreleasepool {
SDL_JoystickDeviceItem *device = joystick->hwdata;
if (device == NULL) {
return SDL_SetError("Controller is no longer connected");
}
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
GCController *controller = device->controller;
GCDeviceLight *light = controller.light;
if (light) {
light.color = [[GCColor alloc] initWithRed:(float)red / 255.0f
@@ -1364,8 +1403,14 @@ IOS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
#ifdef ENABLE_MFI_SENSORS
@autoreleasepool {
SDL_JoystickDeviceItem *device = joystick->hwdata;
if (device == NULL) {
return SDL_SetError("Controller is no longer connected");
}
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
GCController *controller = device->controller;
GCMotion *motion = controller.motion;
if (motion) {
motion.sensorsActive = enabled ? YES : NO;
@@ -1428,7 +1473,6 @@ IOS_JoystickClose(SDL_Joystick *joystick)
#ifdef ENABLE_MFI_SYSTEM_GESTURE_STATE
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
for (id key in controller.physicalInputProfile.buttons) {
GCControllerButtonInput *button = controller.physicalInputProfile.buttons[key];
if ([button isBoundToSystemGesture]) {
@@ -1491,12 +1535,223 @@ IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device)
{
if (is_macos11()) {
return [GCController supportsHIDDevice:device] ? SDL_TRUE : SDL_FALSE;
if ([GCController supportsHIDDevice:device]) {
return SDL_TRUE;
}
/* GCController supportsHIDDevice may return false if the device hasn't been
* seen by the framework yet, so check a few controllers we know are supported.
*/
{
Sint32 vendor = 0;
Sint32 product = 0;
CFTypeRef refCF = NULL;
refCF = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
if (refCF) {
CFNumberGetValue(refCF, kCFNumberSInt32Type, &vendor);
}
refCF = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
if (refCF) {
CFNumberGetValue(refCF, kCFNumberSInt32Type, &product);
}
if (vendor == USB_VENDOR_MICROSOFT && SDL_IsJoystickXboxSeriesX(vendor, product)) {
return SDL_TRUE;
}
}
}
return SDL_FALSE;
}
#endif
#if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE)
static void
GetAppleSFSymbolsNameForElement(GCControllerElement *element, char *name)
{
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (element) {
[element.sfSymbolsName getCString: name maxLength: 255 encoding: NSASCIIStringEncoding];
}
}
}
static GCControllerDirectionPad *
GetDirectionalPadForController(GCController *controller)
{
if (controller.extendedGamepad) {
return controller.extendedGamepad.dpad;
}
if (controller.gamepad) {
return controller.gamepad.dpad;
}
if (controller.microGamepad) {
return controller.microGamepad.dpad;
}
return nil;
}
#endif /* SDL_JOYSTICK_MFI && ENABLE_PHYSICAL_INPUT_PROFILE */
static char elementName[256];
const char *
IOS_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button)
{
elementName[0] = '\0';
#if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE)
if (gamecontroller && SDL_GameControllerGetJoystick(gamecontroller)->driver == &SDL_IOS_JoystickDriver) {
if (@available(iOS 14.0, tvOS 14.0, macOS 11.0, *)) {
GCController *controller = SDL_GameControllerGetJoystick(gamecontroller)->hwdata->controller;
if ([controller respondsToSelector:@selector(physicalInputProfile)]) {
NSDictionary<NSString *,GCControllerElement *> *elements = controller.physicalInputProfile.elements;
switch (button)
{
case SDL_CONTROLLER_BUTTON_A:
GetAppleSFSymbolsNameForElement(elements[GCInputButtonA], elementName);
break;
case SDL_CONTROLLER_BUTTON_B:
GetAppleSFSymbolsNameForElement(elements[GCInputButtonB], elementName);
break;
case SDL_CONTROLLER_BUTTON_X:
GetAppleSFSymbolsNameForElement(elements[GCInputButtonX], elementName);
break;
case SDL_CONTROLLER_BUTTON_Y:
GetAppleSFSymbolsNameForElement(elements[GCInputButtonY], elementName);
break;
case SDL_CONTROLLER_BUTTON_BACK:
GetAppleSFSymbolsNameForElement(elements[GCInputButtonOptions], elementName);
break;
case SDL_CONTROLLER_BUTTON_GUIDE:
GetAppleSFSymbolsNameForElement(elements[GCInputButtonHome], elementName);
break;
case SDL_CONTROLLER_BUTTON_START:
GetAppleSFSymbolsNameForElement(elements[GCInputButtonMenu], elementName);
break;
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
GetAppleSFSymbolsNameForElement(elements[GCInputLeftThumbstickButton], elementName);
break;
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
GetAppleSFSymbolsNameForElement(elements[GCInputRightThumbstickButton], elementName);
break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
GetAppleSFSymbolsNameForElement(elements[GCInputLeftShoulder], elementName);
break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
GetAppleSFSymbolsNameForElement(elements[GCInputRightShoulder], elementName);
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP: {
GCControllerDirectionPad * dpad = GetDirectionalPadForController(controller);
if (dpad) {
GetAppleSFSymbolsNameForElement(dpad.up, elementName);
if (SDL_strlen(elementName) == 0) {
SDL_strlcpy(elementName, "dpad.up.fill", sizeof(elementName));
}
}
break;
}
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: {
GCControllerDirectionPad * dpad = GetDirectionalPadForController(controller);
if (dpad) {
GetAppleSFSymbolsNameForElement(dpad.down, elementName);
if (SDL_strlen(elementName) == 0) {
SDL_strlcpy(elementName, "dpad.down.fill", sizeof(elementName));
}
}
break;
}
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: {
GCControllerDirectionPad * dpad = GetDirectionalPadForController(controller);
if (dpad) {
GetAppleSFSymbolsNameForElement(dpad.left, elementName);
if (SDL_strlen(elementName) == 0) {
SDL_strlcpy(elementName, "dpad.left.fill", sizeof(elementName));
}
}
break;
}
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: {
GCControllerDirectionPad * dpad = GetDirectionalPadForController(controller);
if (dpad) {
GetAppleSFSymbolsNameForElement(dpad.right, elementName);
if (SDL_strlen(elementName) == 0) {
SDL_strlcpy(elementName, "dpad.right.fill", sizeof(elementName));
}
}
break;
}
case SDL_CONTROLLER_BUTTON_MISC1:
GetAppleSFSymbolsNameForElement(elements[GCInputDualShockTouchpadButton], elementName);
break;
case SDL_CONTROLLER_BUTTON_PADDLE1:
GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleOne], elementName);
break;
case SDL_CONTROLLER_BUTTON_PADDLE2:
GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleTwo], elementName);
break;
case SDL_CONTROLLER_BUTTON_PADDLE3:
GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleThree], elementName);
break;
case SDL_CONTROLLER_BUTTON_PADDLE4:
GetAppleSFSymbolsNameForElement(elements[GCInputXboxPaddleFour], elementName);
break;
case SDL_CONTROLLER_BUTTON_TOUCHPAD:
GetAppleSFSymbolsNameForElement(elements[GCInputDualShockTouchpadButton], elementName);
break;
default:
break;
}
}
}
}
#endif
return elementName;
}
const char *
IOS_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis)
{
elementName[0] = '\0';
#if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE)
if (gamecontroller && SDL_GameControllerGetJoystick(gamecontroller)->driver == &SDL_IOS_JoystickDriver) {
if (@available(iOS 14.0, tvOS 14.0, macOS 11.0, *)) {
GCController *controller = SDL_GameControllerGetJoystick(gamecontroller)->hwdata->controller;
if ([controller respondsToSelector:@selector(physicalInputProfile)]) {
NSDictionary<NSString *,GCControllerElement *> *elements = controller.physicalInputProfile.elements;
switch (axis)
{
case SDL_CONTROLLER_AXIS_LEFTX:
GetAppleSFSymbolsNameForElement(elements[GCInputLeftThumbstick], elementName);
break;
case SDL_CONTROLLER_AXIS_LEFTY:
GetAppleSFSymbolsNameForElement(elements[GCInputLeftThumbstick], elementName);
break;
case SDL_CONTROLLER_AXIS_RIGHTX:
GetAppleSFSymbolsNameForElement(elements[GCInputRightThumbstick], elementName);
break;
case SDL_CONTROLLER_AXIS_RIGHTY:
GetAppleSFSymbolsNameForElement(elements[GCInputRightThumbstick], elementName);
break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
GetAppleSFSymbolsNameForElement(elements[GCInputLeftTrigger], elementName);
break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
GetAppleSFSymbolsNameForElement(elements[GCInputRightTrigger], elementName);
break;
default:
break;
}
}
}
}
#endif
return *elementName ? elementName : NULL;
}
SDL_JoystickDriver SDL_IOS_JoystickDriver =
{
IOS_JoystickInit,
@@ -1510,7 +1765,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver =
IOS_JoystickOpen,
IOS_JoystickRumble,
IOS_JoystickRumbleTriggers,
IOS_JoystickHasLED,
IOS_JoystickGetCapabilities,
IOS_JoystickSetLED,
IOS_JoystickSendEffect,
IOS_JoystickSetSensorsEnabled,

View File

@@ -56,6 +56,12 @@
#ifndef SYN_DROPPED
#define SYN_DROPPED 3
#endif
#ifndef BTN_NORTH
#define BTN_NORTH 0x133
#endif
#ifndef BTN_WEST
#define BTN_WEST 0x134
#endif
#ifndef BTN_DPAD_UP
#define BTN_DPAD_UP 0x220
#endif
@@ -85,6 +91,7 @@ typedef enum
static EnumerationMethod enumeration_method = ENUMERATION_UNSET;
static SDL_bool IsJoystickJSNode(const char *node);
static int MaybeAddDevice(const char *path);
static int MaybeRemoveDevice(const char *path);
@@ -105,6 +112,7 @@ typedef struct SDL_joylist_item
SDL_GamepadMapping *mapping;
} SDL_joylist_item;
static SDL_bool SDL_classic_joysticks = SDL_FALSE;
static SDL_joylist_item *SDL_joylist = NULL;
static SDL_joylist_item *SDL_joylist_tail = NULL;
static int numjoysticks = 0;
@@ -176,24 +184,31 @@ GuessIsJoystick(int fd)
}
static int
IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid)
{
struct input_id inpid;
Uint16 *guid16 = (Uint16 *)guid->data;
char *name;
char product_string[128];
/* When udev is enabled we only get joystick devices here, so there's no need to test them */
if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(fd)) {
return 0;
}
if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) >= 0) {
SDL_zero(inpid);
#if SDL_USE_LIBUDEV
SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version);
#endif
} else {
/* When udev is enabled we only get joystick devices here, so there's no need to test them */
if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(fd)) {
return 0;
}
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
return 0;
}
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
return 0;
}
if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) {
return 0;
if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) {
return 0;
}
}
name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string);
@@ -213,7 +228,7 @@ IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
FixupDeviceInfoForMapping(fd, &inpid);
#ifdef DEBUG_JOYSTICK
printf("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
#endif
SDL_memset(guid->data, 0, sizeof(guid->data));
@@ -254,6 +269,15 @@ static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_clas
if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
return;
}
if (SDL_classic_joysticks) {
if (!IsJoystickJSNode(devpath)) {
return;
}
} else {
if (IsJoystickJSNode(devpath)) {
return;
}
}
MaybeAddDevice(devpath);
break;
@@ -268,6 +292,15 @@ static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_clas
}
#endif /* SDL_USE_LIBUDEV */
static void
FreeJoylistItem(SDL_joylist_item *item)
{
SDL_free(item->mapping);
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
}
static int
MaybeAddDevice(const char *path)
{
@@ -293,36 +326,33 @@ MaybeAddDevice(const char *path)
}
}
fd = open(path, O_RDONLY, 0);
fd = open(path, O_RDONLY | O_CLOEXEC, 0);
if (fd < 0) {
return -1;
}
#ifdef DEBUG_INPUT_EVENTS
printf("Checking %s\n", path);
SDL_Log("Checking %s\n", path);
#endif
isstick = IsJoystick(fd, &name, &guid);
isstick = IsJoystick(path, fd, &name, &guid);
close(fd);
if (!isstick) {
return -1;
}
item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
if (item == NULL) {
return -1;
}
SDL_zerop(item);
item->devnum = sb.st_rdev;
item->path = SDL_strdup(path);
item->name = name;
item->guid = guid;
if ((item->path == NULL) || (item->name == NULL)) {
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
FreeJoylistItem(item);
return -1;
}
@@ -342,6 +372,31 @@ MaybeAddDevice(const char *path)
return numjoysticks;
}
static void
RemoveJoylistItem(SDL_joylist_item *item, SDL_joylist_item *prev)
{
if (item->hwdata) {
item->hwdata->item = NULL;
}
if (prev != NULL) {
prev->next = item->next;
} else {
SDL_assert(SDL_joylist == item);
SDL_joylist = item->next;
}
if (item == SDL_joylist_tail) {
SDL_joylist_tail = prev;
}
/* Need to decrement the joystick count before we post the event */
--numjoysticks;
SDL_PrivateJoystickRemoved(item->device_instance);
FreeJoylistItem(item);
}
static int
MaybeRemoveDevice(const char *path)
{
@@ -356,30 +411,7 @@ MaybeRemoveDevice(const char *path)
/* found it, remove it. */
if (SDL_strcmp(path, item->path) == 0) {
const int retval = item->device_instance;
if (item->hwdata) {
item->hwdata->item = NULL;
}
if (prev != NULL) {
prev->next = item->next;
} else {
SDL_assert(SDL_joylist == item);
SDL_joylist = item->next;
}
if (item == SDL_joylist_tail) {
SDL_joylist_tail = prev;
}
/* Need to decrement the joystick count before we post the event */
--numjoysticks;
SDL_PrivateJoystickRemoved(item->device_instance);
if (item->mapping) {
SDL_free(item->mapping);
}
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
RemoveJoylistItem(item, prev);
return retval;
}
prev = item;
@@ -396,26 +428,7 @@ HandlePendingRemovals(void)
while (item != NULL) {
if (item->hwdata && item->hwdata->gone) {
item->hwdata->item = NULL;
if (prev != NULL) {
prev->next = item->next;
} else {
SDL_assert(SDL_joylist == item);
SDL_joylist = item->next;
}
if (item == SDL_joylist_tail) {
SDL_joylist_tail = prev;
}
/* Need to decrement the joystick count before we post the event */
--numjoysticks;
SDL_PrivateJoystickRemoved(item->device_instance);
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
RemoveJoylistItem(item, prev);
if (prev != NULL) {
item = prev->next;
@@ -444,9 +457,7 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG
item->m_bSteamController = SDL_TRUE;
if ((item->path == NULL) || (item->name == NULL)) {
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
FreeJoylistItem(item);
return SDL_FALSE;
}
@@ -474,26 +485,7 @@ static void SteamControllerDisconnectedCallback(int device_instance)
for (item = SDL_joylist; item != NULL; item = item->next) {
/* found it, remove it. */
if (item->device_instance == device_instance) {
if (item->hwdata) {
item->hwdata->item = NULL;
}
if (prev != NULL) {
prev->next = item->next;
} else {
SDL_assert(SDL_joylist == item);
SDL_joylist = item->next;
}
if (item == SDL_joylist_tail) {
SDL_joylist_tail = prev;
}
/* Need to decrement the joystick count before we post the event */
--numjoysticks;
SDL_PrivateJoystickRemoved(item->device_instance);
SDL_free(item->name);
SDL_free(item);
RemoveJoylistItem(item, prev);
return;
}
prev = item;
@@ -539,6 +531,36 @@ StrIsInteger(const char *string)
return 1;
}
static SDL_bool
IsJoystickJSNode(const char *node)
{
const char *last_slash = SDL_strrchr(node, '/');
if (last_slash) {
node = last_slash + 1;
}
return (StrHasPrefix(node, "js") && StrIsInteger(node + 2));
}
static SDL_bool
IsJoystickEventNode(const char *node)
{
const char *last_slash = SDL_strrchr(node, '/');
if (last_slash) {
node = last_slash + 1;
}
return (StrHasPrefix(node, "event") && StrIsInteger(node + 5));
}
static SDL_bool
IsJoystickDeviceNode(const char *node)
{
if (SDL_classic_joysticks) {
return IsJoystickJSNode(node);
} else {
return IsJoystickEventNode(node);
}
}
static void
LINUX_InotifyJoystickDetect(void)
{
@@ -551,6 +573,7 @@ LINUX_InotifyJoystickDetect(void)
ssize_t bytes;
size_t remain = 0;
size_t len;
char path[PATH_MAX];
bytes = read(inotify_fd, &buf, sizeof (buf));
@@ -560,10 +583,7 @@ LINUX_InotifyJoystickDetect(void)
while (remain > 0) {
if (buf.event.len > 0) {
if (StrHasPrefix(buf.event.name, "event") &&
StrIsInteger(buf.event.name + strlen ("event"))) {
char path[PATH_MAX];
if (IsJoystickDeviceNode(buf.event.name)) {
SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", buf.event.name);
if (buf.event.mask & (IN_CREATE | IN_MOVED_TO | IN_ATTRIB)) {
@@ -579,7 +599,7 @@ LINUX_InotifyJoystickDetect(void)
remain -= len;
if (remain != 0) {
memmove (&buf.storage[0], &buf.storage[len], remain);
SDL_memmove (&buf.storage[0], &buf.storage[len], remain);
}
}
}
@@ -592,7 +612,7 @@ LINUX_InotifyJoystickDetect(void)
static int
filter_entries(const struct dirent *entry)
{
return (SDL_strlen(entry->d_name) > 5 && SDL_strncmp(entry->d_name, "event", 5) == 0);
return IsJoystickDeviceNode(entry->d_name);
}
static int
sort_entries(const struct dirent **a, const struct dirent **b)
@@ -659,14 +679,18 @@ LINUX_JoystickDetect(void)
static int
LINUX_JoystickInit(void)
{
const char *devices = SDL_GetHint(SDL_HINT_JOYSTICK_DEVICE);
SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_CLASSIC, SDL_FALSE);
#if SDL_USE_LIBUDEV
if (enumeration_method == ENUMERATION_UNSET) {
if (SDL_getenv("SDL_JOYSTICK_DISABLE_UDEV") != NULL) {
if (SDL_GetHintBoolean("SDL_JOYSTICK_DISABLE_UDEV", SDL_FALSE)) {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
enumeration_method = ENUMERATION_FALLBACK;
}
else if (access("/.flatpak-info", F_OK) == 0
} else if (access("/.flatpak-info", F_OK) == 0
|| access("/run/host/container-manager", F_OK) == 0) {
/* Explicitly check `/.flatpak-info` because, for old versions of
* Flatpak, this was the only available way to tell if we were in
@@ -674,8 +698,8 @@ LINUX_JoystickInit(void)
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"Container detected, disabling udev integration");
enumeration_method = ENUMERATION_FALLBACK;
}
else {
} else {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"Using udev for joystick device discovery");
enumeration_method = ENUMERATION_LIBUDEV;
@@ -684,9 +708,9 @@ LINUX_JoystickInit(void)
#endif
/* First see if the user specified one or more joysticks to use */
if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
if (devices != NULL) {
char *envcopy, *envpath, *delim;
envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE"));
envcopy = SDL_strdup(devices);
envpath = envcopy;
while (envpath != NULL) {
delim = SDL_strchr(envpath, ':');
@@ -706,6 +730,9 @@ LINUX_JoystickInit(void)
last_joy_detect_time = 0;
last_input_dir_mtime = 0;
/* Manually scan first, since we sort by device number and udev doesn't */
LINUX_JoystickDetect();
#if SDL_USE_LIBUDEV
if (enumeration_method == ENUMERATION_LIBUDEV) {
if (SDL_UDEV_Init() < 0) {
@@ -747,9 +774,6 @@ LINUX_JoystickInit(void)
}
}
#endif /* HAVE_INOTIFY */
/* Report all devices currently present */
LINUX_JoystickDetect();
}
return 0;
@@ -854,6 +878,7 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
unsigned long relbit[NBITS(REL_MAX)] = { 0 };
unsigned long ffbit[NBITS(FF_MAX)] = { 0 };
Uint8 key_pam_size, abs_pam_size;
SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE);
/* See if this device uses the new unified event API */
@@ -865,7 +890,7 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
if (test_bit(i, keybit)) {
#ifdef DEBUG_INPUT_EVENTS
printf("Joystick has button: 0x%x\n", i);
SDL_Log("Joystick has button: 0x%x\n", i);
#endif
joystick->hwdata->key_map[i] = joystick->nbuttons;
joystick->hwdata->has_key[i] = SDL_TRUE;
@@ -875,7 +900,7 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
for (i = 0; i < BTN_JOYSTICK; ++i) {
if (test_bit(i, keybit)) {
#ifdef DEBUG_INPUT_EVENTS
printf("Joystick has button: 0x%x\n", i);
SDL_Log("Joystick has button: 0x%x\n", i);
#endif
joystick->hwdata->key_map[i] = joystick->nbuttons;
joystick->hwdata->has_key[i] = SDL_TRUE;
@@ -896,10 +921,10 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
continue;
}
#ifdef DEBUG_INPUT_EVENTS
printf("Joystick has absolute axis: 0x%.2x\n", i);
printf("Values = { %d, %d, %d, %d, %d }\n",
absinfo.value, absinfo.minimum, absinfo.maximum,
absinfo.fuzz, absinfo.flat);
SDL_Log("Joystick has absolute axis: 0x%.2x\n", i);
SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
absinfo.value, absinfo.minimum, absinfo.maximum,
absinfo.fuzz, absinfo.flat);
#endif /* DEBUG_INPUT_EVENTS */
joystick->hwdata->abs_map[i] = joystick->naxes;
joystick->hwdata->has_abs[i] = SDL_TRUE;
@@ -936,10 +961,10 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
continue;
}
#ifdef DEBUG_INPUT_EVENTS
printf("Joystick has hat %d\n", hat_index);
printf("Values = { %d, %d, %d, %d, %d }\n",
absinfo.value, absinfo.minimum, absinfo.maximum,
absinfo.fuzz, absinfo.flat);
SDL_Log("Joystick has hat %d\n", hat_index);
SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
absinfo.value, absinfo.minimum, absinfo.maximum,
absinfo.fuzz, absinfo.flat);
#endif /* DEBUG_INPUT_EVENTS */
joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
@@ -949,16 +974,76 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
++joystick->nballs;
}
/* Allocate data to keep track of these thingamajigs */
if (joystick->nhats > 0) {
if (allocate_hatdata(joystick) < 0) {
joystick->nhats = 0;
} else if ((ioctl(fd, JSIOCGBUTTONS, &key_pam_size, sizeof(key_pam_size)) >= 0) &&
(ioctl(fd, JSIOCGAXES, &abs_pam_size, sizeof(abs_pam_size)) >= 0)) {
size_t len;
joystick->hwdata->classic = SDL_TRUE;
len = (KEY_MAX - BTN_MISC + 1) * sizeof(*joystick->hwdata->key_pam);
joystick->hwdata->key_pam = (Uint16 *)SDL_calloc(1, len);
if (joystick->hwdata->key_pam) {
if (ioctl(fd, JSIOCGBTNMAP, joystick->hwdata->key_pam, len) < 0) {
SDL_free(joystick->hwdata->key_pam);
joystick->hwdata->key_pam = NULL;
key_pam_size = 0;
}
} else {
key_pam_size = 0;
}
for (i = 0; i < key_pam_size; ++i) {
Uint16 code = joystick->hwdata->key_pam[i];
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Joystick has button: 0x%x\n", code);
#endif
joystick->hwdata->key_map[code] = joystick->nbuttons;
joystick->hwdata->has_key[code] = SDL_TRUE;
++joystick->nbuttons;
}
len = ABS_CNT * sizeof(*joystick->hwdata->abs_pam);
joystick->hwdata->abs_pam = (Uint8 *)SDL_calloc(1, len);
if (joystick->hwdata->abs_pam) {
if (ioctl(fd, JSIOCGAXMAP, joystick->hwdata->abs_pam, len) < 0) {
SDL_free(joystick->hwdata->abs_pam);
joystick->hwdata->abs_pam = NULL;
abs_pam_size = 0;
}
} else {
abs_pam_size = 0;
}
for (i = 0; i < abs_pam_size; ++i) {
Uint8 code = joystick->hwdata->abs_pam[i];
if (code >= ABS_HAT0X && code <= ABS_HAT3Y) {
int hat_index = (code - ABS_HAT0X) / 2;
if (!joystick->hwdata->has_hat[hat_index]) {
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Joystick has hat %d\n", hat_index);
#endif
joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
}
} else {
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Joystick has absolute axis: 0x%.2x\n", code);
#endif
joystick->hwdata->abs_map[code] = joystick->naxes;
joystick->hwdata->has_abs[code] = SDL_TRUE;
++joystick->naxes;
}
}
if (joystick->nballs > 0) {
if (allocate_balldata(joystick) < 0) {
joystick->nballs = 0;
}
}
/* Allocate data to keep track of these thingamajigs */
if (joystick->nhats > 0) {
if (allocate_hatdata(joystick) < 0) {
joystick->nhats = 0;
}
}
if (joystick->nballs > 0) {
if (allocate_balldata(joystick) < 0) {
joystick->nballs = 0;
}
}
@@ -985,6 +1070,7 @@ PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item)
joystick->hwdata->guid = item->guid;
joystick->hwdata->effect.id = -1;
joystick->hwdata->m_bSteamController = item->m_bSteamController;
SDL_memset(joystick->hwdata->key_map, 0xFF, sizeof(joystick->hwdata->key_map));
SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map));
if (item->m_bSteamController) {
@@ -993,7 +1079,12 @@ PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item)
&joystick->naxes,
&joystick->nhats);
} else {
const int fd = open(item->path, O_RDWR, 0);
/* Try read-write first, so we can do rumble */
int fd = open(item->path, O_RDWR | O_CLOEXEC, 0);
if (fd < 0) {
/* Try read-only again, at least we'll get events in this case */
fd = open(item->path, O_RDONLY | O_CLOEXEC, 0);
}
if (fd < 0) {
return SDL_SetError("Unable to open %s", item->path);
}
@@ -1099,10 +1190,16 @@ LINUX_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16
return SDL_Unsupported();
}
static SDL_bool
LINUX_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
LINUX_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
Uint32 result = 0;
if (joystick->hwdata->ff_rumble || joystick->hwdata->ff_sine) {
result |= SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -1123,7 +1220,7 @@ LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
return SDL_Unsupported();
}
static SDL_INLINE void
static void
HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
{
struct hwdata_hat *the_hat;
@@ -1148,14 +1245,14 @@ HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
}
}
static SDL_INLINE void
static void
HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
{
stick->hwdata->balls[ball].axis[axis] += value;
}
static SDL_INLINE int
static int
AxisCorrect(SDL_Joystick *joystick, int which, int value)
{
struct axis_correct *correct;
@@ -1189,7 +1286,7 @@ AxisCorrect(SDL_Joystick *joystick, int which, int value)
return value;
}
static SDL_INLINE void
static void
PollAllValues(SDL_Joystick *joystick)
{
struct input_absinfo absinfo;
@@ -1207,7 +1304,7 @@ PollAllValues(SDL_Joystick *joystick)
absinfo.value = AxisCorrect(joystick, i, absinfo.value);
#ifdef DEBUG_INPUT_EVENTS
printf("Joystick : Re-read Axis %d (%d) val= %d\n",
SDL_Log("Joystick : Re-read Axis %d (%d) val= %d\n",
joystick->hwdata->abs_map[i], i, absinfo.value);
#endif
SDL_PrivateJoystickAxis(joystick,
@@ -1237,7 +1334,7 @@ PollAllValues(SDL_Joystick *joystick)
if (joystick->hwdata->has_key[i]) {
const Uint8 value = test_bit(i, keyinfo) ? SDL_PRESSED : SDL_RELEASED;
#ifdef DEBUG_INPUT_EVENTS
printf("Joystick : Re-read Button %d (%d) val= %d\n",
SDL_Log("Joystick : Re-read Button %d (%d) val= %d\n",
joystick->hwdata->key_map[i], i, value);
#endif
SDL_PrivateJoystickButton(joystick,
@@ -1249,12 +1346,11 @@ PollAllValues(SDL_Joystick *joystick)
/* Joyballs are relative input, so there's no poll state. Events only! */
}
static SDL_INLINE void
static void
HandleInputEvents(SDL_Joystick *joystick)
{
struct input_event events[32];
int i, len;
int code;
int i, len, code;
if (joystick->hwdata->fresh) {
PollAllValues(joystick);
@@ -1293,13 +1389,10 @@ HandleInputEvents(SDL_Joystick *joystick)
HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
break;
default:
if (joystick->hwdata->abs_map[code] != 0xFF) {
events[i].value =
AxisCorrect(joystick, code, events[i].value);
SDL_PrivateJoystickAxis(joystick,
joystick->hwdata->abs_map[code],
events[i].value);
}
events[i].value = AxisCorrect(joystick, code, events[i].value);
SDL_PrivateJoystickAxis(joystick,
joystick->hwdata->abs_map[code],
events[i].value);
break;
}
break;
@@ -1318,7 +1411,7 @@ HandleInputEvents(SDL_Joystick *joystick)
switch (code) {
case SYN_DROPPED :
#ifdef DEBUG_INPUT_EVENTS
printf("Event SYN_DROPPED detected\n");
SDL_Log("Event SYN_DROPPED detected\n");
#endif
joystick->hwdata->recovering_from_dropped = SDL_TRUE;
break;
@@ -1343,6 +1436,48 @@ HandleInputEvents(SDL_Joystick *joystick)
}
}
static void
HandleClassicEvents(SDL_Joystick *joystick)
{
struct js_event events[32];
int i, len, code;
joystick->hwdata->fresh = SDL_FALSE;
while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
len /= sizeof(events[0]);
for (i = 0; i < len; ++i) {
switch (events[i].type) {
case JS_EVENT_BUTTON:
code = joystick->hwdata->key_pam[events[i].number];
SDL_PrivateJoystickButton(joystick,
joystick->hwdata->key_map[code],
events[i].value);
break;
case JS_EVENT_AXIS:
code = joystick->hwdata->abs_pam[events[i].number];
switch (code) {
case ABS_HAT0X:
case ABS_HAT0Y:
case ABS_HAT1X:
case ABS_HAT1Y:
case ABS_HAT2X:
case ABS_HAT2Y:
case ABS_HAT3X:
case ABS_HAT3Y:
code -= ABS_HAT0X;
HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
break;
default:
SDL_PrivateJoystickAxis(joystick,
joystick->hwdata->abs_map[code],
events[i].value);
break;
}
}
}
}
}
static void
LINUX_JoystickUpdate(SDL_Joystick *joystick)
{
@@ -1353,7 +1488,11 @@ LINUX_JoystickUpdate(SDL_Joystick *joystick)
return;
}
HandleInputEvents(joystick);
if (joystick->hwdata->classic) {
HandleClassicEvents(joystick);
} else {
HandleInputEvents(joystick);
}
/* Deliver ball motion updates */
for (i = 0; i < joystick->nballs; ++i) {
@@ -1384,6 +1523,8 @@ LINUX_JoystickClose(SDL_Joystick *joystick)
if (joystick->hwdata->item) {
joystick->hwdata->item->hwdata = NULL;
}
SDL_free(joystick->hwdata->key_pam);
SDL_free(joystick->hwdata->abs_pam);
SDL_free(joystick->hwdata->hats);
SDL_free(joystick->hwdata->balls);
SDL_free(joystick->hwdata->fname);
@@ -1405,9 +1546,7 @@ LINUX_JoystickQuit(void)
for (item = SDL_joylist; item; item = next) {
next = item->next;
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
FreeJoylistItem(item);
}
SDL_joylist = SDL_joylist_tail = NULL;
@@ -1446,6 +1585,7 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
SDL_OutOfMemory();
return SDL_FALSE;
}
SDL_memcpy(&joystick->guid, &item->guid, sizeof(item->guid));
joystick->hwdata = (struct joystick_hwdata *)
SDL_calloc(1, sizeof(*joystick->hwdata));
@@ -1484,14 +1624,27 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
out->b.target = joystick->hwdata->key_map[BTN_B];
}
if (joystick->hwdata->has_key[BTN_X]) {
out->x.kind = EMappingKind_Button;
out->x.target = joystick->hwdata->key_map[BTN_X];
}
/* Xbox controllers use BTN_X and BTN_Y, and PS4 controllers use BTN_WEST and BTN_NORTH */
if (SDL_JoystickGetVendor(joystick) == USB_VENDOR_SONY) {
if (joystick->hwdata->has_key[BTN_WEST]) {
out->x.kind = EMappingKind_Button;
out->x.target = joystick->hwdata->key_map[BTN_WEST];
}
if (joystick->hwdata->has_key[BTN_Y]) {
out->y.kind = EMappingKind_Button;
out->y.target = joystick->hwdata->key_map[BTN_Y];
if (joystick->hwdata->has_key[BTN_NORTH]) {
out->y.kind = EMappingKind_Button;
out->y.target = joystick->hwdata->key_map[BTN_NORTH];
}
} else {
if (joystick->hwdata->has_key[BTN_X]) {
out->x.kind = EMappingKind_Button;
out->x.target = joystick->hwdata->key_map[BTN_X];
}
if (joystick->hwdata->has_key[BTN_Y]) {
out->y.kind = EMappingKind_Button;
out->y.target = joystick->hwdata->key_map[BTN_Y];
}
}
if (joystick->hwdata->has_key[BTN_SELECT]) {
@@ -1552,20 +1705,20 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
out->lefttrigger.target = hat | 0x4;
out->righttrigger.target = hat | 0x2;
} else {
if (joystick->hwdata->has_key[BTN_TL2]) {
out->lefttrigger.kind = EMappingKind_Button;
out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
} else if (joystick->hwdata->has_abs[ABS_Z]) {
if (joystick->hwdata->has_abs[ABS_Z]) {
out->lefttrigger.kind = EMappingKind_Axis;
out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z];
} else if (joystick->hwdata->has_key[BTN_TL2]) {
out->lefttrigger.kind = EMappingKind_Button;
out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
}
if (joystick->hwdata->has_key[BTN_TR2]) {
out->righttrigger.kind = EMappingKind_Button;
out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
} else if (joystick->hwdata->has_abs[ABS_RZ]) {
if (joystick->hwdata->has_abs[ABS_RZ]) {
out->righttrigger.kind = EMappingKind_Axis;
out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ];
} else if (joystick->hwdata->has_key[BTN_TR2]) {
out->righttrigger.kind = EMappingKind_Button;
out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
}
}
@@ -1643,7 +1796,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver =
LINUX_JoystickOpen,
LINUX_JoystickRumble,
LINUX_JoystickRumbleTriggers,
LINUX_JoystickHasLED,
LINUX_JoystickGetCapabilities,
LINUX_JoystickSetLED,
LINUX_JoystickSendEffect,
LINUX_JoystickSetSensorsEnabled,

View File

@@ -56,6 +56,11 @@ struct joystick_hwdata
SDL_bool has_key[KEY_MAX];
SDL_bool has_abs[ABS_MAX];
/* Support for the classic joystick interface */
SDL_bool classic;
Uint16 *key_pam;
Uint8 *abs_pam;
struct axis_correct
{
SDL_bool use_deadzones;

View File

@@ -147,7 +147,7 @@ struct _joycfg
/* OS/2 Implementation Function Prototypes */
static int joyPortOpen(HFILE * hGame);
static void joyPortClose(HFILE * hGame);
static int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars);
static int joyGetData(const char *joyenv, char *name, char stopchar, size_t maxchars);
static int joyGetEnv(struct _joycfg * joydata);
@@ -421,13 +421,11 @@ static int OS2_JoystickOpen(SDL_Joystick *joystick, int device_index)
int i; /* Generic Counter */
/* allocate memory for system specific hardware data */
joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata));
if (joystick->hwdata == NULL)
joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata));
if (!joystick->hwdata)
{
return SDL_OutOfMemory();
}
/* Reset Hardware Data */
SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
/* ShortCut Pointer */
index = device_index;
@@ -440,14 +438,14 @@ static int OS2_JoystickOpen(SDL_Joystick *joystick, int device_index)
if ((i < 2) || i < SYS_JoyData[index].axes)
{
joystick->hwdata->transaxes[i].offset = ((SDL_JOYSTICK_AXIS_MAX + SDL_JOYSTICK_AXIS_MIN)>>1) - SYS_JoyData[index].axes_med[i];
joystick->hwdata->transaxes[i].scale1 = (float)abs((SDL_JOYSTICK_AXIS_MIN/SYS_JoyData[index].axes_min[i]));
joystick->hwdata->transaxes[i].scale2 = (float)abs((SDL_JOYSTICK_AXIS_MAX/SYS_JoyData[index].axes_max[i]));
joystick->hwdata->transaxes[i].scale1 = (float)SDL_abs((SDL_JOYSTICK_AXIS_MIN/SYS_JoyData[index].axes_min[i]));
joystick->hwdata->transaxes[i].scale2 = (float)SDL_abs((SDL_JOYSTICK_AXIS_MAX/SYS_JoyData[index].axes_max[i]));
}
else
{
joystick->hwdata->transaxes[i].offset = 0;
joystick->hwdata->transaxes[i].scale1 = 1.0; /* Just in case */
joystick->hwdata->transaxes[i].scale2 = 1.0; /* Just in case */
joystick->hwdata->transaxes[i].scale1 = 1.0f; /* Just in case */
joystick->hwdata->transaxes[i].scale2 = 1.0f; /* Just in case */
}
}
@@ -474,9 +472,9 @@ static int OS2_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble
return SDL_Unsupported();
}
static SDL_bool OS2_JoystickHasLED(SDL_Joystick *joystick)
static Uint32 OS2_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
static int OS2_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
@@ -567,7 +565,7 @@ static void OS2_JoystickUpdate(SDL_Joystick *joystick)
if (SYS_JoyData[index].id == 1) corr = 2;
else corr = 0;
normbut = 4; /* Number of normal buttons */
if (joystick->nbuttons<normbut) normbut = joystick->nbuttons;
if (joystick->nbuttons < normbut) normbut = joystick->nbuttons;
for (i = corr; (i-corr) < normbut; ++i)
{
/*
@@ -700,7 +698,7 @@ static void joyPortClose(HFILE * hGame)
/***************************/
static int joyGetEnv(struct _joycfg * joydata)
{
char *joyenv; /* Pointer to tested character */
const char *joyenv; /* Pointer to tested character */
char tempnumber[5]; /* Temporary place to put numeric texts */
joyenv = SDL_getenv("SDL_OS2_JOYSTICK");
@@ -711,30 +709,29 @@ static int joyGetEnv(struct _joycfg * joydata)
/* If the string name starts with '... get if fully */
if (*joyenv == '\'') joyenv += joyGetData(++joyenv,joydata->name,'\'',sizeof(joydata->name));
/* If not, get it until the next space */
else if (*joyenv == '\"') joyenv+=joyGetData(++joyenv,joydata->name,'\"',sizeof(joydata->name));
else if (*joyenv == '\"') joyenv += joyGetData(++joyenv,joydata->name,'\"',sizeof(joydata->name));
else joyenv += joyGetData(joyenv,joydata->name,' ',sizeof(joydata->name));
/* Now get the number of axes */
while (*joyenv == ' ' && *joyenv != 0) joyenv++; /* jump spaces... */
joyenv += joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
joydata->axes = atoi(tempnumber);
joydata->axes = SDL_atoi(tempnumber);
/* Now get the number of buttons */
while (*joyenv == ' ' && *joyenv != 0) joyenv++; /* jump spaces... */
joyenv += joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
joydata->buttons = atoi(tempnumber);
joydata->buttons = SDL_atoi(tempnumber);
/* Now get the number of hats */
while (*joyenv == ' ' && *joyenv != 0) joyenv++; /* jump spaces... */
joyenv += joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
joydata->hats = atoi(tempnumber);
joydata->hats = SDL_atoi(tempnumber);
/* Now get the number of balls */
while (*joyenv==' ' && *joyenv != 0) joyenv++; /* jump spaces... */
joyenv += joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber));
joydata->balls = atoi(tempnumber);
joydata->balls = SDL_atoi(tempnumber);
return 1;
}
@@ -742,7 +739,7 @@ static int joyGetEnv(struct _joycfg * joydata)
/* Get a text from in the string starting in joyenv until it finds */
/* the stopchar or maxchars is reached. The result is placed in name. */
/************************************************************************/
static int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars)
static int joyGetData(const char *joyenv, char *name, char stopchar, size_t maxchars)
{
char *nameptr; /* Pointer to the selected character */
int chcnt = 0; /* Count how many characters where copied */
@@ -780,7 +777,7 @@ SDL_JoystickDriver SDL_OS2_JoystickDriver =
OS2_JoystickOpen,
OS2_JoystickRumble,
OS2_JoystickRumbleTriggers,
OS2_JoystickHasLED,
OS2_JoystickGetCapabilities,
OS2_JoystickSetLED,
OS2_JoystickSendEffect,
OS2_JoystickSetSensorsEnabled,

View File

@@ -209,9 +209,9 @@ PSP_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 ri
return SDL_Unsupported();
}
static SDL_bool PSP_JoystickHasLED(SDL_Joystick *joystick)
static Uint32 PSP_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
static int
@@ -311,7 +311,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver =
PSP_JoystickOpen,
PSP_JoystickRumble,
PSP_JoystickRumbleTriggers,
PSP_JoystickHasLED,
PSP_JoystickGetCapabilities,
PSP_JoystickSetLED,
PSP_JoystickSendEffect,
PSP_JoystickSetSensorsEnabled,

View File

@@ -39,40 +39,45 @@
#define USB_VENDOR_SONY 0x054c
#define USB_VENDOR_VALVE 0x28de
#define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419
#define USB_PRODUCT_GOOGLE_STADIA_CONTROLLER 0x9400
#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER 0x1846
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337
#define USB_PRODUCT_NINTENDO_SWITCH_PRO 0x2009
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_LEFT 0x2006
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT 0x2007
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP 0x200e
#define USB_PRODUCT_RAZER_PANTHERA 0x0401
#define USB_PRODUCT_RAZER_PANTHERA_EVO 0x1008
#define USB_PRODUCT_RAZER_ATROX 0x0a00
#define USB_PRODUCT_SONY_DS4 0x05c4
#define USB_PRODUCT_SONY_DS4_DONGLE 0x0ba0
#define USB_PRODUCT_SONY_DS4_SLIM 0x09cc
#define USB_PRODUCT_SONY_DS5 0x0ce6
#define USB_PRODUCT_XBOX360_XUSB_CONTROLLER 0x02a1 /* XUSB driver software PID */
#define USB_PRODUCT_XBOX360_WIRED_CONTROLLER 0x028e
#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER 0x0719
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 0x02e3
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 0x0b00
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH 0x0b05
#define USB_PRODUCT_XBOX_ONE_S 0x02ea
#define USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH 0x02e0
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH 0x02fd
#define USB_PRODUCT_XBOX_SERIES_X 0x0b12
#define USB_PRODUCT_XBOX_SERIES_X_BLUETOOTH 0x0b13
#define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6
#define USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE 0x02d9
#define USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW 0x02da
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 0x4001
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA 0x4002
#define USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER 0x02ff /* XBOXGIP driver software PID */
#define USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER 0x02fe /* Made up product ID for XInput */
#define USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD 0x11ff
#define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419
#define USB_PRODUCT_GOOGLE_STADIA_CONTROLLER 0x9400
#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER 0x1846
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337
#define USB_PRODUCT_NINTENDO_SWITCH_PRO 0x2009
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_LEFT 0x2006
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT 0x2007
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP 0x200e
#define USB_PRODUCT_RAZER_PANTHERA 0x0401
#define USB_PRODUCT_RAZER_PANTHERA_EVO 0x1008
#define USB_PRODUCT_RAZER_ATROX 0x0a00
#define USB_PRODUCT_SONY_DS4 0x05c4
#define USB_PRODUCT_SONY_DS4_DONGLE 0x0ba0
#define USB_PRODUCT_SONY_DS4_SLIM 0x09cc
#define USB_PRODUCT_SONY_DS5 0x0ce6
#define USB_PRODUCT_XBOX360_XUSB_CONTROLLER 0x02a1 /* XUSB driver software PID */
#define USB_PRODUCT_XBOX360_WIRED_CONTROLLER 0x028e
#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER 0x0719
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE 0x0b0a
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH 0x0b0c
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLE 0x0b21
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 0x02e3
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 0x0b00
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH 0x0b05
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLE 0x0b22
#define USB_PRODUCT_XBOX_ONE_S 0x02ea
#define USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH 0x02e0
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH 0x02fd
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLE 0x0b20
#define USB_PRODUCT_XBOX_SERIES_X 0x0b12
#define USB_PRODUCT_XBOX_SERIES_X_BLE 0x0b13
#define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6
#define USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE 0x02d9
#define USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW 0x02da
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 0x4001
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA 0x4002
#define USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER 0x02ff /* XBOXGIP driver software PID */
#define USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER 0x02fe /* Made up product ID for XInput */
#define USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD 0x11ff
/* USB usage pages */
#define USB_USAGEPAGE_GENERIC_DESKTOP 0x0001

View File

@@ -345,10 +345,10 @@ VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint1
}
static SDL_bool
VIRTUAL_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
VIRTUAL_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
return 0;
}
@@ -442,7 +442,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver =
VIRTUAL_JoystickOpen,
VIRTUAL_JoystickRumble,
VIRTUAL_JoystickRumbleTriggers,
VIRTUAL_JoystickHasLED,
VIRTUAL_JoystickGetCapabilities,
VIRTUAL_JoystickSetLED,
VIRTUAL_JoystickSendEffect,
VIRTUAL_JoystickSetSensorsEnabled,

View File

@@ -365,11 +365,11 @@ VITA_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right)
return SDL_Unsupported();
}
static SDL_bool
VITA_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
VITA_JoystickGetCapabilities(SDL_Joystick *joystick)
{
// always return true for now
return SDL_TRUE;
// always return LED and rumble supported for now
return SDL_JOYCAP_LED | SDL_JOYCAP_RUMBLE;
}
@@ -409,7 +409,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver =
VITA_JoystickRumble,
VITA_JoystickRumbleTriggers,
VITA_JoystickHasLED,
VITA_JoystickGetCapabilities,
VITA_JoystickSetLED,
VITA_JoystickSendEffect,
VITA_JoystickSetSensorsEnabled,

View File

@@ -238,10 +238,21 @@ SDL_IsXInputDevice(Uint16 vendor_id, Uint16 product_id, const char* hidPath)
{
SDL_GameControllerType type;
if (!SDL_XINPUT_Enabled()) {
/* XInput and RawInput backends will pick up XInput-compatible devices */
if (!SDL_XINPUT_Enabled()
#ifdef SDL_JOYSTICK_RAWINPUT
&& !RAWINPUT_IsEnabled()
#endif
) {
return SDL_FALSE;
}
/* If device path contains "IG_" then its an XInput device */
/* See: https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput */
if (SDL_strstr(hidPath, "IG_") != NULL) {
return SDL_TRUE;
}
type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0);
if (type == SDL_CONTROLLER_TYPE_XBOX360 ||
type == SDL_CONTROLLER_TYPE_XBOXONE ||
@@ -249,12 +260,6 @@ SDL_IsXInputDevice(Uint16 vendor_id, Uint16 product_id, const char* hidPath)
return SDL_TRUE;
}
/* If device path contains "IG_" then its an XInput device */
/* See: https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput */
if (SDL_strstr(hidPath, "IG_") != NULL) {
return SDL_TRUE;
}
return SDL_FALSE;
}
@@ -427,7 +432,7 @@ SDL_DINPUT_JoystickInit(void)
static BOOL CALLBACK
EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
{
#define CHECK(exp) { if(!(exp)) goto err; }
#define CHECK(expression) { if(!(expression)) goto err; }
JoyStick_DeviceData *pNewJoystick = NULL;
JoyStick_DeviceData *pPrevJoystick = NULL;
Uint16 *guid16;
@@ -548,11 +553,12 @@ typedef struct
static BOOL CALLBACK
EnumJoystickPresentCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
{
#define CHECK(exp) { if(!(exp)) goto err; }
#define CHECK(expression) { if(!(expression)) goto err; }
Joystick_PresentData *pData = (Joystick_PresentData *)pContext;
Uint16 vendor = 0;
Uint16 product = 0;
LPDIRECTINPUTDEVICE8 device = NULL;
BOOL result = DIENUM_CONTINUE;
/* We are only supporting HID devices. */
CHECK((pDeviceInstance->dwDevType & DIDEVTYPE_HID) != 0);
@@ -562,7 +568,7 @@ EnumJoystickPresentCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext
if (vendor == pData->vendor && product == pData->product) {
pData->present = SDL_TRUE;
return DIENUM_STOP; /* get next device, please */
result = DIENUM_STOP; /* found it */
}
err:
@@ -570,7 +576,7 @@ err:
IDirectInputDevice8_Release(device);
}
return DIENUM_CONTINUE; /* get next device, please */
return result;
#undef CHECK
}
@@ -919,6 +925,18 @@ SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble,
return 0;
}
Uint32
SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick * joystick)
{
Uint32 result = 0;
if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
result |= SDL_JOYCAP_RUMBLE;
}
return result;
}
static Uint8
TranslatePOV(DWORD value)
{
@@ -1163,6 +1181,12 @@ SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble,
return SDL_Unsupported();
}
Uint32
SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick * joystick)
{
return 0;
}
void
SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
{

View File

@@ -25,6 +25,7 @@ extern void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
extern int SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
extern int SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
extern Uint32 SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick * joystick);
extern void SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick);
extern void SDL_DINPUT_JoystickClose(SDL_Joystick * joystick);
extern void SDL_DINPUT_JoystickQuit(void);

View File

@@ -40,6 +40,7 @@
#include "SDL_timer.h"
#include "../usb_ids.h"
#include "../SDL_sysjoystick.h"
#include "../controller_type.h"
#include "../../core/windows/SDL_windows.h"
#include "../../core/windows/SDL_hid.h"
#include "../hidapi/SDL_hidapijoystick_c.h"
@@ -47,7 +48,7 @@
#ifdef HAVE_XINPUT_H
#define SDL_JOYSTICK_RAWINPUT_XINPUT
#endif
#ifdef SDL_WINDOWS10_SDK
#ifdef HAVE_WINDOWS_GAMING_INPUT_H
#define SDL_JOYSTICK_RAWINPUT_WGI
#endif
@@ -102,6 +103,7 @@ typedef struct _SDL_RAWINPUT_Device
Uint16 version;
SDL_JoystickGUID guid;
SDL_bool is_xinput;
SDL_bool is_xboxone;
PHIDP_PREPARSED_DATA preparsed_data;
HANDLE hDevice;
@@ -114,6 +116,7 @@ typedef struct _SDL_RAWINPUT_Device
struct joystick_hwdata
{
SDL_bool is_xinput;
SDL_bool is_xboxone;
PHIDP_PREPARSED_DATA preparsed_data;
ULONG max_data_length;
HIDP_DATA *data;
@@ -449,12 +452,12 @@ RAWINPUT_UpdateWindowsGamingInput()
wgi_state.dirty = SDL_FALSE;
if (wgi_state.need_device_list_update) {
HRESULT hr;
__FIVectorView_1_Windows__CGaming__CInput__CGamepad *gamepads;
wgi_state.need_device_list_update = SDL_FALSE;
for (ii = 0; ii < wgi_state.per_gamepad_count; ii++) {
wgi_state.per_gamepad[ii]->connected = SDL_FALSE;
}
HRESULT hr;
__FIVectorView_1_Windows__CGaming__CInput__CGamepad *gamepads;
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_get_Gamepads(wgi_state.gamepad_statics, &gamepads);
if (SUCCEEDED(hr)) {
@@ -479,13 +482,15 @@ RAWINPUT_UpdateWindowsGamingInput()
}
if (!found) {
/* New device, add it */
WindowsGamingInputGamepadState *gamepad_state;
wgi_state.per_gamepad_count++;
wgi_state.per_gamepad = SDL_realloc(wgi_state.per_gamepad, sizeof(wgi_state.per_gamepad[0]) * wgi_state.per_gamepad_count);
if (!wgi_state.per_gamepad) {
SDL_OutOfMemory();
return;
}
WindowsGamingInputGamepadState *gamepad_state = SDL_calloc(1, sizeof(*gamepad_state));
gamepad_state = SDL_calloc(1, sizeof(*gamepad_state));
if (!gamepad_state) {
SDL_OutOfMemory();
return;
@@ -531,6 +536,10 @@ RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
wgi_state.need_device_list_update = SDL_TRUE;
wgi_state.ref_count++;
if (!wgi_state.initialized) {
static const IID SDL_IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
HRESULT hr;
HMODULE hModule;
/* I think this takes care of RoInitialize() in a way that is compatible with the rest of SDL */
if (FAILED(WIN_CoInitialize())) {
return;
@@ -538,9 +547,7 @@ RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
wgi_state.initialized = SDL_TRUE;
wgi_state.dirty = SDL_TRUE;
static const IID SDL_IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
HRESULT hr;
HMODULE hModule = LoadLibraryA("combase.dll");
hModule = LoadLibraryA("combase.dll");
if (hModule != NULL) {
typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
@@ -554,7 +561,7 @@ RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
RoGetActivationFactoryFunc(hNamespaceString, &SDL_IID_IGamepadStatics, &wgi_state.gamepad_statics);
RoGetActivationFactoryFunc(hNamespaceString, &SDL_IID_IGamepadStatics, (void **)&wgi_state.gamepad_statics);
}
}
FreeLibrary(hModule);
@@ -672,7 +679,7 @@ RAWINPUT_DeviceFromHandle(HANDLE hDevice)
static void
RAWINPUT_AddDevice(HANDLE hDevice)
{
#define CHECK(exp) { if(!(exp)) goto err; }
#define CHECK(expression) { if(!(expression)) goto err; }
SDL_RAWINPUT_Device *device = NULL;
SDL_RAWINPUT_Device *curr, *last;
RID_DEVICE_INFO rdi;
@@ -705,6 +712,7 @@ RAWINPUT_AddDevice(HANDLE hDevice)
device->product_id = (Uint16)rdi.hid.dwProductId;
device->version = (Uint16)rdi.hid.dwVersionNumber;
device->is_xinput = SDL_TRUE;
device->is_xboxone = GuessControllerType(device->vendor_id, device->product_id) == k_eControllerType_XBoxOneController;
{
const Uint16 vendor = device->vendor_id;
@@ -1054,6 +1062,7 @@ RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
}
ctx->is_xinput = device->is_xinput;
ctx->is_xboxone = device->is_xboxone;
ctx->preparsed_data = device->preparsed_data;
ctx->max_data_length = SDL_HidP_MaxDataListLength(HidP_Input, ctx->preparsed_data);
ctx->data = (HIDP_DATA *)SDL_malloc(ctx->max_data_length * sizeof(*ctx->data));
@@ -1268,7 +1277,7 @@ RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
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 SDL_SetError("Setting vibration failed: 0x%lx\n", hr);
}
}
return 0;
@@ -1277,10 +1286,29 @@ RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
#endif
}
static SDL_bool
RAWINPUT_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
RAWINPUT_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
Uint32 result = 0;
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
if (ctx->is_xinput) {
result |= SDL_JOYCAP_RUMBLE;
}
#endif
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
if (ctx->is_xinput) {
result |= SDL_JOYCAP_RUMBLE;
if (ctx->is_xboxone) {
result |= SDL_JOYCAP_RUMBLE_TRIGGERS;
}
}
#endif
return result;
}
static int
@@ -1520,7 +1548,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
SDL_bool new_correlation_count = 0;
if (RAWINPUT_MissingWindowsGamingInputSlot()) {
Uint8 correlation_id;
WindowsGamingInputGamepadState *slot_idx;
WindowsGamingInputGamepadState *slot_idx = NULL;
if (RAWINPUT_GuessWindowsGamingInputSlot(&match_state_xinput, &correlation_id, &slot_idx)) {
/* we match exactly one WindowsGamingInput device */
/* Probably can do without wgi_correlation_count, just check and clear wgi_slot to NULL, unless we need
@@ -1829,9 +1857,9 @@ RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT result = -1;
SDL_LockMutex(SDL_RAWINPUT_mutex);
if (SDL_RAWINPUT_inited) {
SDL_LockMutex(SDL_RAWINPUT_mutex);
switch (msg) {
case WM_INPUT_DEVICE_CHANGE:
{
@@ -1875,9 +1903,9 @@ RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
result = 0;
break;
}
}
SDL_UnlockMutex(SDL_RAWINPUT_mutex);
SDL_UnlockMutex(SDL_RAWINPUT_mutex);
}
if (result >= 0) {
return result;
@@ -1892,8 +1920,6 @@ RAWINPUT_JoystickQuit(void)
return;
}
SDL_LockMutex(SDL_RAWINPUT_mutex);
while (SDL_RAWINPUT_devices) {
RAWINPUT_DelDevice(SDL_RAWINPUT_devices, SDL_FALSE);
}
@@ -1904,7 +1930,6 @@ RAWINPUT_JoystickQuit(void)
SDL_RAWINPUT_inited = SDL_FALSE;
SDL_UnlockMutex(SDL_RAWINPUT_mutex);
SDL_DestroyMutex(SDL_RAWINPUT_mutex);
SDL_RAWINPUT_mutex = NULL;
}
@@ -1928,7 +1953,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver =
RAWINPUT_JoystickOpen,
RAWINPUT_JoystickRumble,
RAWINPUT_JoystickRumbleTriggers,
RAWINPUT_JoystickHasLED,
RAWINPUT_JoystickGetCapabilities,
RAWINPUT_JoystickSetLED,
RAWINPUT_JoystickSendEffect,
RAWINPUT_JoystickSetSensorsEnabled,

View File

@@ -31,6 +31,8 @@
#include "../../core/windows/SDL_windows.h"
#define COBJMACROS
#include "windows.gaming.input.h"
#include <cfgmgr32.h>
#include <roapi.h>
struct joystick_hwdata
@@ -77,15 +79,15 @@ static const IID IID_IGameController = { 0x1BAF6522, 0x5F64, 0x42C5, { 0x82, 0x6
static const IID IID_IGameControllerBatteryInfo = { 0xDCECC681, 0x3963, 0x4DA6, { 0x95, 0x5D, 0x55, 0x3F, 0x3B, 0x6F, 0x61, 0x61 } };
static const IID IID_IArcadeStickStatics = { 0x5C37B8C8, 0x37B1, 0x4AD8, { 0x94, 0x58, 0x20, 0x0F, 0x1A, 0x30, 0x01, 0x8E } };
static const IID IID_IArcadeStickStatics2 = { 0x52B5D744, 0xBB86, 0x445A, { 0xB5, 0x9C, 0x59, 0x6F, 0x0E, 0x2A, 0x49, 0xDF } };
static const IID IID_IArcadeStick = { 0xB14A539D, 0xBEFB, 0x4C81, { 0x80, 0x51, 0x15, 0xEC, 0xF3, 0xB1, 0x30, 0x36 } };
/*static const IID IID_IArcadeStick = { 0xB14A539D, 0xBEFB, 0x4C81, { 0x80, 0x51, 0x15, 0xEC, 0xF3, 0xB1, 0x30, 0x36 } };*/
static const IID IID_IFlightStickStatics = { 0x5514924A, 0xFECC, 0x435E, { 0x83, 0xDC, 0x5C, 0xEC, 0x8A, 0x18, 0xA5, 0x20 } };
static const IID IID_IFlightStick = { 0xB4A2C01C, 0xB83B, 0x4459, { 0xA1, 0xA9, 0x97, 0xB0, 0x3C, 0x33, 0xDA, 0x7C } };
/*static const IID IID_IFlightStick = { 0xB4A2C01C, 0xB83B, 0x4459, { 0xA1, 0xA9, 0x97, 0xB0, 0x3C, 0x33, 0xDA, 0x7C } };*/
static const IID IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
static const IID IID_IGamepadStatics2 = { 0x42676DC5, 0x0856, 0x47C4, { 0x92, 0x13, 0xB3, 0x95, 0x50, 0x4C, 0x3A, 0x3C } };
static const IID IID_IGamepad = { 0xBC7BB43C, 0x0A69, 0x3903, { 0x9E, 0x9D, 0xA5, 0x0F, 0x86, 0xA4, 0x5D, 0xE5 } };
/*static const IID IID_IGamepad = { 0xBC7BB43C, 0x0A69, 0x3903, { 0x9E, 0x9D, 0xA5, 0x0F, 0x86, 0xA4, 0x5D, 0xE5 } };*/
static const IID IID_IRacingWheelStatics = { 0x3AC12CD5, 0x581B, 0x4936, { 0x9F, 0x94, 0x69, 0xF1, 0xE6, 0x51, 0x4C, 0x7D } };
static const IID IID_IRacingWheelStatics2 = { 0xE666BCAA, 0xEDFD, 0x4323, { 0xA9, 0xF6, 0x3C, 0x38, 0x40, 0x48, 0xD1, 0xED } };
static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };
/*static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };*/
extern SDL_bool SDL_XINPUT_Enabled(void);
extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
@@ -93,11 +95,17 @@ extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16
static SDL_bool
SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
{
#ifdef SDL_JOYSTICK_XINPUT
PRAWINPUTDEVICELIST raw_devices = NULL;
UINT i, raw_device_count = 0;
LONG vidpid = MAKELONG(vendor, product);
if (!SDL_XINPUT_Enabled()) {
/* XInput and RawInput backends will pick up XInput-compatible devices */
if (!SDL_XINPUT_Enabled()
#ifdef SDL_JOYSTICK_RAWINPUT
&& !RAWINPUT_IsEnabled()
#endif
) {
return SDL_FALSE;
}
@@ -123,17 +131,70 @@ SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
char devName[MAX_PATH];
UINT rdiSize = sizeof(rdi);
UINT nameSize = SDL_arraysize(devName);
DEVINST devNode;
char devVidPidString[32];
int j;
rdi.cbSize = sizeof(rdi);
if ((raw_devices[i].dwType == RIM_TYPEHID) &&
(GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == vidpid) &&
(GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
(SDL_strstr(devName, "IG_") != NULL)) {
if ((raw_devices[i].dwType != RIM_TYPEHID) ||
(GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == ((UINT)-1)) ||
(GetRawInputDeviceInfoA(raw_devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) == ((UINT)-1)) ||
(SDL_strstr(devName, "IG_") == NULL)) {
/* Skip non-XInput devices */
continue;
}
/* First check for a simple VID/PID match. This will work for Xbox 360 controllers. */
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == vidpid) {
SDL_free(raw_devices);
return SDL_TRUE;
}
/* For Xbox One controllers, Microsoft doesn't propagate the VID/PID down to the HID stack.
* We'll have to walk the device tree upwards searching for a match for our VID/PID. */
/* Make sure the device interface string is something we know how to parse */
/* Example: \\?\HID#VID_045E&PID_02FF&IG_00#9&2c203035&2&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} */
if ((SDL_strstr(devName, "\\\\?\\") != devName) || (SDL_strstr(devName, "#{") == NULL)) {
continue;
}
/* Unescape the backslashes in the string and terminate before the GUID portion */
for (j = 0; devName[j] != '\0'; j++) {
if (devName[j] == '#') {
if (devName[j + 1] == '{') {
devName[j] = '\0';
break;
} else {
devName[j] = '\\';
}
}
}
/* We'll be left with a string like this: \\?\HID\VID_045E&PID_02FF&IG_00\9&2c203035&2&0000
* Simply skip the \\?\ prefix and we'll have a properly formed device instance ID */
if (CM_Locate_DevNodeA(&devNode, &devName[4], CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) {
continue;
}
SDL_snprintf(devVidPidString, sizeof(devVidPidString), "VID_%04X&PID_%04X", vendor, product);
while (CM_Get_Parent(&devNode, devNode, 0) == CR_SUCCESS) {
char deviceId[MAX_DEVICE_ID_LEN];
if ((CM_Get_Device_IDA(devNode, deviceId, SDL_arraysize(deviceId), 0) == CR_SUCCESS) &&
(SDL_strstr(deviceId, devVidPidString) != NULL)) {
/* The VID/PID matched a parent device */
SDL_free(raw_devices);
return SDL_TRUE;
}
}
}
SDL_free(raw_devices);
#endif /* SDL_JOYSTICK_XINPUT */
return SDL_FALSE;
}
@@ -166,7 +227,13 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
HRESULT hr;
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller = NULL;
hr = IUnknown_QueryInterface((IUnknown *)e, &IID_IRawGameController, (void **)&controller);
/* We can get delayed calls to InvokeAdded() after WGI_JoystickQuit(). Do nothing if WGI is deinitialized.
* FIXME: Can we tell if WGI has been quit and reinitialized prior to a delayed callback? */
if (wgi.statics == NULL) {
return S_OK;
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID_IRawGameController, (void **)&controller);
if (SUCCEEDED(hr)) {
char *name = NULL;
SDL_JoystickGUID guid;
@@ -184,26 +251,37 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2);
if (SUCCEEDED(hr)) {
typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length);
typedef HRESULT (WINAPI *WindowsDeleteString_t)(HSTRING string);
WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = NULL;
WindowsDeleteString_t WindowsDeleteStringFunc = NULL;
#ifdef __WINRT__
WindowsGetStringRawBufferFunc = WindowsGetStringRawBuffer;
WindowsDeleteStringFunc = WindowsDeleteString;
#else
HMODULE hModule = LoadLibraryA("combase.dll");
if (hModule != NULL) {
typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length);
typedef HRESULT (WINAPI *WindowsDeleteString_t)(HSTRING string);
WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer");
WindowsDeleteString_t WindowsDeleteStringFunc = (WindowsDeleteString_t)GetProcAddress(hModule, "WindowsDeleteString");
if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) {
HSTRING hString;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString);
if (SUCCEEDED(hr)) {
PCWSTR string = WindowsGetStringRawBufferFunc(hString, NULL);
if (string) {
name = WIN_StringToUTF8W(string);
}
WindowsDeleteStringFunc(hString);
WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer");
WindowsDeleteStringFunc = (WindowsDeleteString_t)GetProcAddress(hModule, "WindowsDeleteString");
}
#endif /* __WINRT__ */
if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) {
HSTRING hString;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString);
if (SUCCEEDED(hr)) {
PCWSTR string = WindowsGetStringRawBufferFunc(hString, NULL);
if (string) {
name = WIN_StringToUTF8W(string);
}
WindowsDeleteStringFunc(hString);
}
}
#ifndef __WINRT__
if (hModule != NULL) {
FreeLibrary(hModule);
}
#endif
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
if (!name) {
@@ -310,7 +388,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeRemo
HRESULT hr;
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller = NULL;
hr = IUnknown_QueryInterface((IUnknown *)e, &IID_IRawGameController, (void **)&controller);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID_IRawGameController, (void **)&controller);
if (SUCCEEDED(hr)) {
int i;
@@ -361,87 +439,120 @@ static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController controlle
static int
WGI_JoystickInit(void)
{
typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
#ifndef __WINRT__
HMODULE hModule;
#endif
HRESULT hr;
if (FAILED(WIN_CoInitialize())) {
return SDL_SetError("CoInitialize() failed");
}
HRESULT hr;
HMODULE hModule = LoadLibraryA("combase.dll");
#ifdef __WINRT__
WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
RoGetActivationFactoryFunc = RoGetActivationFactory;
#else
hModule = LoadLibraryA("combase.dll");
if (hModule != NULL) {
typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
typedef HRESULT (WINAPI *WindowsDeleteString_t)(HSTRING string);
typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)GetProcAddress(hModule, "WindowsCreateStringReference");
RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
}
#endif /* __WINRT__ */
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
PCWSTR pNamespace;
HSTRING_HEADER hNamespaceStringHeader;
HSTRING hNamespaceString;
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)GetProcAddress(hModule, "WindowsCreateStringReference");
RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
PCWSTR pNamespace;
HSTRING_HEADER hNamespaceStringHeader;
HSTRING hNamespaceString;
pNamespace = L"Windows.Gaming.Input.RawGameController";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRawGameControllerStatics, &wgi.statics);
if (!SUCCEEDED(hr)) {
SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%x", hr);
}
}
pNamespace = L"Windows.Gaming.Input.ArcadeStick";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IArcadeStickStatics, &wgi.arcade_stick_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID_IArcadeStickStatics2, &wgi.arcade_stick_statics2);
} else {
SDL_SetError("Couldn't find IID_IArcadeStickStatics: 0x%x", hr);
}
}
pNamespace = L"Windows.Gaming.Input.FlightStick";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IFlightStickStatics, &wgi.flight_stick_statics);
if (!SUCCEEDED(hr)) {
SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%x", hr);
}
}
pNamespace = L"Windows.Gaming.Input.Gamepad";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, &wgi.gamepad_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, &wgi.gamepad_statics2);
} else {
SDL_SetError("Couldn't find IGamepadStatics: 0x%x", hr);
}
}
pNamespace = L"Windows.Gaming.Input.RacingWheel";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, &wgi.racing_wheel_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID_IRacingWheelStatics2, &wgi.racing_wheel_statics2);
} else {
SDL_SetError("Couldn't find IRacingWheelStatics: 0x%x", hr);
}
pNamespace = L"Windows.Gaming.Input.RawGameController";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRawGameControllerStatics, (void **)&wgi.statics);
if (!SUCCEEDED(hr)) {
SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%lx", hr);
}
}
pNamespace = L"Windows.Gaming.Input.ArcadeStick";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IArcadeStickStatics, (void **)&wgi.arcade_stick_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID_IArcadeStickStatics2, (void **)&wgi.arcade_stick_statics2);
} else {
SDL_SetError("Couldn't find IID_IArcadeStickStatics: 0x%lx", hr);
}
}
pNamespace = L"Windows.Gaming.Input.FlightStick";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IFlightStickStatics, (void **)&wgi.flight_stick_statics);
if (!SUCCEEDED(hr)) {
SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%lx", hr);
}
}
pNamespace = L"Windows.Gaming.Input.Gamepad";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, (void **)&wgi.gamepad_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, (void **)&wgi.gamepad_statics2);
} else {
SDL_SetError("Couldn't find IGamepadStatics: 0x%lx", hr);
}
}
pNamespace = L"Windows.Gaming.Input.RacingWheel";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, (void **)&wgi.racing_wheel_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID_IRacingWheelStatics2, (void **)&wgi.racing_wheel_statics2);
} else {
SDL_SetError("Couldn't find IRacingWheelStatics: 0x%lx", hr);
}
}
}
#ifndef __WINRT__
if (hModule != NULL) {
FreeLibrary(hModule);
}
#endif
if (wgi.statics) {
__FIVectorView_1_Windows__CGaming__CInput__CRawGameController *controllers;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerAdded(wgi.statics, &controller_added, &wgi.controller_added_token);
if (!SUCCEEDED(hr)) {
SDL_SetError("add_RawGameControllerAdded() failed: 0x%x\n", hr);
SDL_SetError("add_RawGameControllerAdded() failed: 0x%lx\n", hr);
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerRemoved(wgi.statics, &controller_removed, &wgi.controller_removed_token);
if (!SUCCEEDED(hr)) {
SDL_SetError("add_RawGameControllerRemoved() failed: 0x%x\n", hr);
SDL_SetError("add_RawGameControllerRemoved() failed: 0x%lx\n", hr);
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_get_RawGameControllers(wgi.statics, &controllers);
if (SUCCEEDED(hr)) {
unsigned i, count = 0;
hr = __FIVectorView_1_Windows__CGaming__CInput__CRawGameController_get_Size(controllers, &count);
if (SUCCEEDED(hr)) {
for (i = 0; i < count; ++i) {
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller = NULL;
hr = __FIVectorView_1_Windows__CGaming__CInput__CRawGameController_GetAt(controllers, i, &controller);
if (SUCCEEDED(hr) && controller) {
IEventHandler_CRawGameControllerVtbl_InvokeAdded(&controller_added, NULL, controller);
}
}
}
}
}
@@ -574,7 +685,7 @@ WGI_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 h
if (SUCCEEDED(hr)) {
return 0;
} else {
return SDL_SetError("Setting vibration failed: 0x%x\n", hr);
return SDL_SetError("Setting vibration failed: 0x%lx\n", hr);
}
} else {
return SDL_Unsupported();
@@ -595,17 +706,24 @@ WGI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 ri
if (SUCCEEDED(hr)) {
return 0;
} else {
return SDL_SetError("Setting vibration failed: 0x%x\n", hr);
return SDL_SetError("Setting vibration failed: 0x%lx\n", hr);
}
} else {
return SDL_Unsupported();
}
}
static SDL_bool
WGI_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
WGI_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
struct joystick_hwdata *hwdata = joystick->hwdata;
if (hwdata->gamepad) {
/* FIXME: Can WGI even tell us if trigger rumble is supported? */
return SDL_JOYCAP_RUMBLE | SDL_JOYCAP_RUMBLE_TRIGGERS;
} else {
return 0;
}
}
static int
@@ -713,7 +831,7 @@ WGI_JoystickQuit(void)
{
if (wgi.statics) {
while (wgi.controller_count > 0) {
IEventHandler_CRawGameControllerVtbl_InvokeRemoved(&controller_removed, NULL, (__x_ABI_CWindows_CGaming_CInput_CIRawGameController *)wgi.controllers[wgi.controller_count - 1].controller);
IEventHandler_CRawGameControllerVtbl_InvokeRemoved(&controller_removed, NULL, wgi.controllers[wgi.controller_count - 1].controller);
}
if (wgi.controllers) {
SDL_free(wgi.controllers);
@@ -813,7 +931,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver =
WGI_JoystickOpen,
WGI_JoystickRumble,
WGI_JoystickRumbleTriggers,
WGI_JoystickHasLED,
WGI_JoystickGetCapabilities,
WGI_JoystickSetLED,
WGI_JoystickSendEffect,
WGI_JoystickSetSensorsEnabled,

View File

@@ -151,7 +151,7 @@ static DWORD CALLBACK
SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID context, CM_NOTIFY_ACTION action, PCM_NOTIFY_EVENT_DATA eventData, DWORD event_data_size)
{
if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL ||
action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) {
action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) {
s_bWindowsDeviceChanged = SDL_TRUE;
}
return ERROR_SUCCESS;
@@ -179,15 +179,15 @@ SDL_CreateDeviceNotificationFunc(void)
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;
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(&notify_filter, NULL, SDL_DeviceNotificationFunc, &s_DeviceNotificationFuncHandle) == CR_SUCCESS) {
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(&notify_filter, NULL, SDL_DeviceNotificationFunc, &s_DeviceNotificationFuncHandle) == CR_SUCCESS) {
return SDL_TRUE;
}
}
}
}
@@ -658,10 +658,14 @@ WINDOWS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint1
return SDL_Unsupported();
}
static SDL_bool
WINDOWS_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
WINDOWS_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return SDL_FALSE;
if (joystick->hwdata->bXInputDevice) {
return SDL_XINPUT_JoystickGetCapabilities(joystick);
} else {
return SDL_DINPUT_JoystickGetCapabilities(joystick);
}
}
static int
@@ -758,7 +762,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
WINDOWS_JoystickOpen,
WINDOWS_JoystickRumble,
WINDOWS_JoystickRumbleTriggers,
WINDOWS_JoystickHasLED,
WINDOWS_JoystickGetCapabilities,
WINDOWS_JoystickSetLED,
WINDOWS_JoystickSendEffect,
WINDOWS_JoystickSetSensorsEnabled,

View File

@@ -503,6 +503,12 @@ SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble,
return 0;
}
Uint32
SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick * joystick)
{
return SDL_JOYCAP_RUMBLE;
}
void
SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
{
@@ -579,6 +585,12 @@ SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble,
return SDL_Unsupported();
}
Uint32
SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick * joystick)
{
return 0;
}
void
SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
{

View File

@@ -27,6 +27,7 @@ extern int SDL_XINPUT_JoystickInit(void);
extern void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
extern int SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
extern int SDL_XINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
extern Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick * joystick);
extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick);
extern void SDL_XINPUT_JoystickClose(SDL_Joystick * joystick);
extern void SDL_XINPUT_JoystickQuit(void);