Merge commit '852f2a6343518919e5ca8d3c1bbcab9f493e3cd8'

This commit is contained in:
2024-01-17 17:02:59 +01:00
1244 changed files with 50102 additions and 28146 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -30,12 +30,11 @@
*/
static const char *s_GamepadMappings[] = {
#ifdef SDL_JOYSTICK_XINPUT
"xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"xinput,*,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
#endif
#ifdef SDL_JOYSTICK_WGI
"03000000491900001904000000007700,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,",
"03000000d11800000094000000007700,Google Stadia 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:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"030000007e0500000920000000007701,Nintendo Switch Pro Controller,a:b1,b:b0,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:b3,y:b2,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000007e0500000920000000007701,Nintendo Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000004c050000c405000000007701,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,",
"030000004c050000e60c000000007700,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:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
@ -44,53 +43,30 @@ static const char *s_GamepadMappings[] = {
#endif
#ifdef SDL_JOYSTICK_DINPUT
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,",
"03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001038000000000000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001038000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000650000000000000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000650000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000012ab000000000000,8BitDo NES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000012ab000000000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000022000000090000000000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000203800000900000000000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000660000000000000,8BitDo Pro 2,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001290000000000000,8BitDo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001290000000000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00006228000000000000,8BitDo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00006228000000000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000020ab000000000000,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000020ab000000000000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001130000000000000,8BitDo Ultimate Wired 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:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
"03000000c82d00001330000000000000,8BitDo Ultimate 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:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
"03000000c82d00001890000000000000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00003032000000000000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000a00500003232000000000000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000a00500003232000000000000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000050b00000579000000000000,ASUS ROG Kunai 3 Gamepad,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
"03000000050b00000679000000000000,ASUS ROG Kunai 3 Gamepad,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:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
@ -224,10 +200,8 @@ static const char *s_GamepadMappings[] = {
"03000000152000000182000000000000,NGDS,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,",
"030000005509000000b4000000000000,NVIDIA Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000004b120000014d000000000000,NYKO AIRFLO EX,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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"03000000790000004318000000000000,Nintendo GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000790000004318000000000000,Nintendo GameCube Controller,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,",
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b1,b:b0,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:b3,y:b2,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,",
"03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
@ -278,6 +252,7 @@ static const char *s_GamepadMappings[] = {
"03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,",
"03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,",
"03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,",
"030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,",
"03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000321500000204000000000000,Razer Panthera (PS3),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,",
"03000000321500000104000000000000,Razer Panthera (PS4),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,",
@ -293,7 +268,6 @@ static const char *s_GamepadMappings[] = {
"030000000d0f00005c00000000000000,Real Arcade Pro.V4,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,",
"0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,",
"0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,",
"03000000790000001100000000000000,Retrolink SNES Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000006b140000130d000000000000,Revolution Pro Controller 3,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,",
"030000006b140000010d000000000000,Revolution Pro 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,",
@ -356,51 +330,31 @@ static const char *s_GamepadMappings[] = {
"03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,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,",
"03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,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:a2,righty:a3,start:b9,x:b3,y:b0,",
"03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,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:a2,righty:a3,start:b9,x:b3,y:b0,",
"03000000830500006020000000000000,iBuffalo SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000101c0000171c000000000000,uRage Gamepad,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,",
#endif
#ifdef __MACOS__
"03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000650000001000000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a5,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000650000001000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a5,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000022000000090000001000000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000203800000900000000010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000660000000020000,8BitDo Pro 2,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000102800000900000000000000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001130000000020000,8BitDo Ultimate Wired 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,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"03000000c82d00001330000000020000,8BitDo Ultimate 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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"03000000c82d00001890000001000000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00003032000000010000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000a00500003232000008010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000a00500003232000008010000,8BitDo Zero Gamepad,a:b1,b:b2,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000a00500003232000009010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000a00500003232000009010000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000050b00000579000000010000,ASUS ROG Kunai 3 Gamepad,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,",
"03000000050b00000679000000010000,ASUS ROG Kunai 3 Gamepad,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,",
@ -452,7 +406,6 @@ static const char *s_GamepadMappings[] = {
"03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,",
"030000004b120000014d000000010000,NYKO AIRFLO EX,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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,",
"050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000006f0e00000901000002010000,PDP Versus Fighting Pad,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,",
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
@ -473,7 +426,6 @@ static const char *s_GamepadMappings[] = {
"03000000321500000009000000020000,Razer Serval,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"0300000032150000030a000000000000,Razer Wildcat,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,",
"03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,",
"03000000790000001100000006010000,Retrolink SNES Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000006b140000130d000000010000,Revolution Pro Controller 3,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,",
"030000006b140000010d000000010000,Revolution Pro 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,",
@ -515,67 +467,40 @@ static const char *s_GamepadMappings[] = {
"03000000c0160000e105000000040000,Xin-Mo Dual Arcade,crc:82d5,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,", /* Ultimate Atari Fight Stick */
"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,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,",
"03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,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,",
"03000000830500006020000000010000,iBuffalo SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,",
#endif
#if defined(SDL_JOYSTICK_LINUX) || defined(__OpenBSD__)
"03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000650000011010000,8BitDo M30 Gamepad,a:b0,b:b1,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a5,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000012ab000010010000,8BitDo NES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000012ab000010010000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000022000000090000011010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000203800000900000000010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000020000000000000,8BitDo Pro 2 Wired Controller for Xbox,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,",
"06000000c82d00000020000006010000,8BitDo Pro 2 Wired Controller for Xbox,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,",
"03000000c82d00000660000011010000,8BitDo Pro 2,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00000660000000010000,8BitDo Pro 2,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000102800000900000000010000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000102800000900000000010000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00003028000000010000,8BitDo SFC30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00003028000000010000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000020ab000010010000,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000003512000020ab000010010000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000202800000900000000010000,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000202800000900000000010000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001130000011010000,8BitDo Ultimate Wired 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,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"03000000c82d00001330000011010000,8BitDo Ultimate 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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"03000000c82d00001890000011010000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00003032000000010000,8BitDo Zero 2,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000a00500003232000001000000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000a00500003232000001000000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000031000011010000,8Bitdo Receiver,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,",
"03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00006228000000010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00006228000000010000,8Bitdo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,",
"05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,",
@ -593,6 +518,7 @@ static const char *s_GamepadMappings[] = {
"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: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,",
"05000000503200000210000000000000128804098,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,",
@ -632,7 +558,7 @@ static const char *s_GamepadMappings[] = {
"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,",
"030000000d0f00008800000011010000,HORI Fighting Stick mini 4 (PS3),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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000000d0f00008700000011010000,HORI Fighting Stick mini 4 (PS4),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,rightshoulder:b5,rightstick:b11,righttrigger:a4,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,",
"030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,",
"030000000d0f0000aa00000011010000,HORI Real Arcade Pro,a:b2,b:b1,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:b3,y:b0,",
"030000000d0f00006e00000011010000,HORIPAD 4 (PS3),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,",
"030000000d0f00006600000011010000,HORIPAD 4 (PS4),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,",
@ -696,32 +622,18 @@ static const char *s_GamepadMappings[] = {
"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"030000004b120000014d000000010000,NYKO AIRFLO EX,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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"03000000451300000830000010010000,NYKO CORE,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:a5,start:b9,x:b0,y:b3,",
"03000000790000004318000010010000,Nintendo GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000790000004318000010010000,Nintendo GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,",
"050000007e0500000620000001800000,Nintendo Switch Joy-Con (L),a:b15,b:b16,guide:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b17,y:b14,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000620000001800000,Nintendo Switch Joy-Con (L),a:b16,b:b15,guide:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"060000007e0500000620000000000000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"060000007e0500000620000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"060000007e0500000820000000000000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"060000007e0500000820000000000000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000720000001800000,Nintendo Switch Joy-Con (R),a:b2,b:b1,guide:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b3,y:b0,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000720000001800000,Nintendo Switch Joy-Con (R),a:b1,b:b2,guide:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000d620000013a7000011010000,Nintendo Switch PowerA Controller,a:b2,b:b1,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:b3,y:b0,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000d620000013a7000011010000,Nintendo Switch PowerA Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus Controller,a:b2,b:b1,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:b3,y:b0,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000004c69632050726f20436f6e00,Nintendo Switch Pro Controller,crc:15b7,a:b1,b:b0,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000004c69632050726f20436f6e00,Nintendo Switch Pro Controller,crc:15b7,a:b0,b:b1,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b1,b:b0,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:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000603000000060000,Nintendo Wii Remote Classic Controller,crc:0d8a,a:b0,b:b1,back:b10,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000603000000060000,Nintendo Wii Remote Classic Controller,crc:0d8a,a:b1,b:b0,back:b10,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e0500000603000000060000,Nintendo Wii Remote,crc:60be,a:b1,b:b0,back:b4,dpdown:b8,dpleft:b6,dpright:b7,dpup:b5,guide:b2,start:b3,x:b9,y:b10,",
"05000000010000000100000003000000,Nintendo Wiimote,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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
@ -784,7 +696,6 @@ static const char *s_GamepadMappings[] = {
"050000003215000000090000163a0000,Razer Serval,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"0300000032150000030a000001010000,Razer Wildcat,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,",
"0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,",
"03000000790000001100000010010000,Retrolink SNES Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b0,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"030000006b140000130d000011010000,Revolution Pro Controller 3,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,",
"030000006b140000010d000011010000,Revolution Pro 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,",
@ -816,6 +727,7 @@ static const char *s_GamepadMappings[] = {
"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
"05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
"03000000de2800000512000000016800,Steam Deck,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle1:b12,paddle2:b13,paddle3:b14,paddle4:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
"03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,",
"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,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,",
@ -857,7 +769,6 @@ static const char *s_GamepadMappings[] = {
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,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,",
"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
"030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,",
"03000000830500006020000010010000,iBuffalo SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,",
@ -870,37 +781,21 @@ static const char *s_GamepadMappings[] = {
"030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4~,start:b7,x:b2,y:b3,",
#endif
#ifdef __ANDROID__
"05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b0,b:b1,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b0,b:b1,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b20,b:b21,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b23,y:b24,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,",
"0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
@ -908,12 +803,9 @@ static const char *s_GamepadMappings[] = {
"050000005509000003720000cf7f3f00,NVIDIA Controller v01.01,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,",
"050000005509000010720000ffff3f00,NVIDIA Controller v01.03,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,",
"050000005509000014720000df7f3f80,NVIDIA Controller v01.04,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,",
"050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,sdk>=:29,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,sdk>=:29,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,sdk<=:28,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", /* Extremely slow in Bluetooth mode on Android */
"050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b2,y:b17,sdk<=:28,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", /* Extremely slow in Bluetooth mode on Android */
"050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,",
"030000004c050000cc09000000006800,PS4 Controller,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,",
"050000004c050000c405000000783f00,PS4 Controller,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,",
"050000004c050000c4050000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,",
"050000004c050000c4050000ffff3f00,PS4 Controller,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,",
@ -938,7 +830,6 @@ static const char *s_GamepadMappings[] = {
"050000005e040000130b0000ffff3f00,Xbox Series X Controller,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,",
"050000005e04000091020000ff073f80,Xbox Wireless Controller,a:b0,b:b1,back:b4,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,", /* The DPAD doesn't seem to work on this controller on Android TV? */
"050000001727000044310000ffff3f80,XiaoMi Game Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a4,righty:a5,start:b6,x:b2,y:b3,",
"0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
#endif
#ifdef SDL_JOYSTICK_MFI
@ -949,19 +840,12 @@ static const char *s_GamepadMappings[] = {
"05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,",
"050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
"050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,",
"050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b1,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,",
"050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,",

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -32,6 +32,7 @@ extern "C" {
#endif
struct SDL_JoystickDriver;
struct SDL_SteamVirtualGamepadInfo;
extern char SDL_joystick_magic;
/* Initialization and shutdown functions */
@ -53,16 +54,13 @@ extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_l
/* Function to return whether there are any joysticks opened by the application */
extern SDL_bool SDL_JoysticksOpened(void);
/* Function to get the next available joystick instance ID */
extern SDL_JoystickID SDL_GetNextJoystickInstanceID(void);
/* Function to standardize the name for a controller
This should be freed with SDL_free() when no longer needed
*/
extern char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name);
/* Function to create a GUID for a joystick based on the VID/PID and name */
extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data);
extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *vendor_name, const char *product_name, Uint8 driver_signature, Uint8 driver_data);
/* Function to create a GUID for a joystick based on the name, with no VID/PID information */
extern SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name);
@ -83,6 +81,9 @@ extern void SDL_SetJoystickGUIDCRC(SDL_JoystickGUID *guid, Uint16 crc);
extern SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI);
extern SDL_GamepadType SDL_GetGamepadTypeFromGUID(SDL_JoystickGUID guid, const char *name);
/* Function to return whether a joystick GUID uses the version field */
extern SDL_bool SDL_JoystickGUIDUsesVersion(SDL_JoystickGUID guid);
/* Function to return whether a joystick is an Xbox One controller */
extern SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id);
@ -111,6 +112,9 @@ extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16
extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id);
extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id);
/* Function to return whether a joystick is a Nintendo GameCube style controller */
extern SDL_bool SDL_IsJoystickGameCube(Uint16 vendor_id, Uint16 product_id);
/* Function to return whether a joystick is an Amazon Luna controller */
extern SDL_bool SDL_IsJoystickAmazonLunaController(Uint16 vendor_id, Uint16 product_id);
@ -123,6 +127,9 @@ extern SDL_bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 pr
/* Function to return whether a joystick is a Steam Controller */
extern SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id);
/* Function to return whether a joystick is a Steam Deck */
extern SDL_bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id);
/* Function to return whether a joystick guid comes from the XInput driver */
extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid);
@ -132,6 +139,9 @@ extern SDL_bool SDL_IsJoystickWGI(SDL_JoystickGUID guid);
/* Function to return whether a joystick guid comes from the HIDAPI driver */
extern SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid);
/* Function to return whether a joystick guid comes from the MFI driver */
extern SDL_bool SDL_IsJoystickMFI(SDL_JoystickGUID guid);
/* Function to return whether a joystick guid comes from the RAWINPUT driver */
extern SDL_bool SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid);
@ -161,21 +171,27 @@ extern int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick,
extern void SDL_SendJoystickBatteryLevel(SDL_Joystick *joystick,
SDL_JoystickPowerLevel ePowerLevel);
/* Function to get the Steam virtual gamepad info for a joystick */
extern const struct SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id);
/* Internal sanity checking functions */
extern SDL_bool SDL_IsJoystickValid(SDL_Joystick *joystick);
typedef enum
{
EMappingKind_None = 0,
EMappingKind_Button = 1,
EMappingKind_Axis = 2,
EMappingKind_Hat = 3
EMappingKind_None,
EMappingKind_Button,
EMappingKind_Axis,
EMappingKind_Hat,
} EMappingKind;
typedef struct SDL_InputMapping
{
EMappingKind kind;
Uint8 target;
SDL_bool axis_reversed;
SDL_bool half_axis_positive;
SDL_bool half_axis_negative;
} SDL_InputMapping;
typedef struct SDL_GamepadMapping
@ -206,6 +222,7 @@ typedef struct SDL_GamepadMapping
SDL_InputMapping righty;
SDL_InputMapping lefttrigger;
SDL_InputMapping righttrigger;
SDL_InputMapping touchpad;
} SDL_GamepadMapping;
/* Function to get autodetected gamepad controller mapping from the driver */
@ -215,12 +232,24 @@ extern SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(SDL_JoystickID instance
typedef struct
{
int num_entries;
int max_entries;
Uint32 *entries;
const char *included_hint_name;
int num_included_entries;
int max_included_entries;
Uint32 *included_entries;
const char *excluded_hint_name;
int num_excluded_entries;
int max_excluded_entries;
Uint32 *excluded_entries;
int num_initial_entries;
Uint32 *initial_entries;
SDL_bool initialized;
} SDL_vidpid_list;
extern void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list);
extern void SDL_LoadVIDPIDList(SDL_vidpid_list *list);
extern void SDL_LoadVIDPIDListFromHints(SDL_vidpid_list *list, const char *included_list, const char *excluded_list);
extern SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_list *list);
extern void SDL_FreeVIDPIDList(SDL_vidpid_list *list);

View File

@ -0,0 +1,248 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
#ifdef __WIN32__
#include "../core/windows/SDL_windows.h"
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#define SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE "SteamVirtualGamepadInfo"
static char *SDL_steam_virtual_gamepad_info_file SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static Uint64 SDL_steam_virtual_gamepad_info_file_mtime SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static Uint64 SDL_steam_virtual_gamepad_info_check_time SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static SDL_SteamVirtualGamepadInfo **SDL_steam_virtual_gamepad_info SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static int SDL_steam_virtual_gamepad_info_count SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static Uint64 GetFileModificationTime(const char *file)
{
Uint64 modification_time = 0;
#ifdef __WIN32__
WCHAR *wFile = WIN_UTF8ToStringW(file);
if (wFile) {
HANDLE hFile = CreateFileW(wFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
FILETIME last_write_time;
if (GetFileTime(hFile, NULL, NULL, &last_write_time)) {
modification_time = last_write_time.dwHighDateTime;
modification_time <<= 32;
modification_time |= last_write_time.dwLowDateTime;
}
CloseHandle(hFile);
}
SDL_free(wFile);
}
#else
struct stat sb;
if (stat(file, &sb) == 0) {
modification_time = (Uint64)sb.st_mtime;
}
#endif
return modification_time;
}
static void SDL_FreeSteamVirtualGamepadInfo(void)
{
int i;
SDL_AssertJoysticksLocked();
for (i = 0; i < SDL_steam_virtual_gamepad_info_count; ++i) {
SDL_SteamVirtualGamepadInfo *entry = SDL_steam_virtual_gamepad_info[i];
if (entry) {
SDL_free(entry->name);
SDL_free(entry);
}
}
SDL_free(SDL_steam_virtual_gamepad_info);
SDL_steam_virtual_gamepad_info = NULL;
SDL_steam_virtual_gamepad_info_count = 0;
}
static void AddVirtualGamepadInfo(int slot, SDL_SteamVirtualGamepadInfo *info)
{
SDL_SteamVirtualGamepadInfo *new_info;
SDL_AssertJoysticksLocked();
if (slot < 0) {
return;
}
if (slot >= SDL_steam_virtual_gamepad_info_count) {
SDL_SteamVirtualGamepadInfo **slots = (SDL_SteamVirtualGamepadInfo **)SDL_realloc(SDL_steam_virtual_gamepad_info, (slot + 1)*sizeof(*SDL_steam_virtual_gamepad_info));
if (!slots) {
return;
}
while (SDL_steam_virtual_gamepad_info_count <= slot) {
slots[SDL_steam_virtual_gamepad_info_count++] = NULL;
}
SDL_steam_virtual_gamepad_info = slots;
}
if (SDL_steam_virtual_gamepad_info[slot]) {
/* We already have this slot info */
return;
}
new_info = (SDL_SteamVirtualGamepadInfo *)SDL_malloc(sizeof(*new_info));
if (!new_info) {
return;
}
SDL_copyp(new_info, info);
SDL_steam_virtual_gamepad_info[slot] = new_info;
SDL_zerop(info);
}
void SDL_InitSteamVirtualGamepadInfo(void)
{
const char *file;
SDL_AssertJoysticksLocked();
file = SDL_GetHint(SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE);
if (file && *file) {
SDL_steam_virtual_gamepad_info_file = SDL_strdup(file);
}
SDL_UpdateSteamVirtualGamepadInfo();
}
SDL_bool SDL_SteamVirtualGamepadEnabled(void)
{
SDL_AssertJoysticksLocked();
return (SDL_steam_virtual_gamepad_info != NULL);
}
SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void)
{
const int UPDATE_CHECK_INTERVAL_MS = 3000;
Uint64 now;
Uint64 mtime;
char *data, *end, *next, *line, *value;
size_t size;
int slot, new_slot;
SDL_SteamVirtualGamepadInfo info;
SDL_AssertJoysticksLocked();
if (!SDL_steam_virtual_gamepad_info_file) {
return SDL_FALSE;
}
now = SDL_GetTicks();
if (SDL_steam_virtual_gamepad_info_check_time &&
now < (SDL_steam_virtual_gamepad_info_check_time + UPDATE_CHECK_INTERVAL_MS)) {
return SDL_FALSE;
}
SDL_steam_virtual_gamepad_info_check_time = now;
mtime = GetFileModificationTime(SDL_steam_virtual_gamepad_info_file);
if (mtime == 0 || mtime == SDL_steam_virtual_gamepad_info_file_mtime) {
return SDL_FALSE;
}
data = (char *)SDL_LoadFile(SDL_steam_virtual_gamepad_info_file, &size);
if (!data) {
return SDL_FALSE;
}
SDL_FreeSteamVirtualGamepadInfo();
slot = -1;
SDL_zero(info);
for (next = data, end = data + size; next < end; ) {
while (next < end && (*next == '\0' || *next == '\r' || *next == '\n')) {
++next;
}
line = next;
while (next < end && (*next != '\r' && *next != '\n')) {
++next;
}
*next = '\0';
if (SDL_sscanf(line, "[slot %d]", &new_slot) == 1) {
if (slot >= 0) {
AddVirtualGamepadInfo(slot, &info);
}
slot = new_slot;
} else {
value = SDL_strchr(line, '=');
if (value) {
*value++ = '\0';
if (SDL_strcmp(line, "name") == 0) {
SDL_free(info.name);
info.name = SDL_strdup(value);
} else if (SDL_strcmp(line, "VID") == 0) {
info.vendor_id = (Uint16)SDL_strtoul(value, NULL, 0);
} else if (SDL_strcmp(line, "PID") == 0) {
info.product_id = (Uint16)SDL_strtoul(value, NULL, 0);
} else if (SDL_strcmp(line, "type") == 0) {
info.type = SDL_GetGamepadTypeFromString(value);
} else if (SDL_strcmp(line, "handle") == 0) {
info.handle = SDL_strtoull(value, NULL, 0);
}
}
}
}
if (slot >= 0) {
AddVirtualGamepadInfo(slot, &info);
}
SDL_free(data);
SDL_steam_virtual_gamepad_info_file_mtime = mtime;
return SDL_TRUE;
}
const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot)
{
SDL_AssertJoysticksLocked();
if (slot < 0 || slot >= SDL_steam_virtual_gamepad_info_count) {
return NULL;
}
return SDL_steam_virtual_gamepad_info[slot];
}
void SDL_QuitSteamVirtualGamepadInfo(void)
{
SDL_AssertJoysticksLocked();
if (SDL_steam_virtual_gamepad_info_file) {
SDL_FreeSteamVirtualGamepadInfo();
SDL_free(SDL_steam_virtual_gamepad_info_file);
SDL_steam_virtual_gamepad_info_file = NULL;
}
}

View File

@ -0,0 +1,36 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
typedef struct SDL_SteamVirtualGamepadInfo
{
Uint64 handle;
char *name;
Uint16 vendor_id;
Uint16 product_id;
SDL_GamepadType type;
} SDL_SteamVirtualGamepadInfo;
void SDL_InitSteamVirtualGamepadInfo(void);
SDL_bool SDL_SteamVirtualGamepadEnabled(void);
SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void);
const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot);
void SDL_QuitSteamVirtualGamepadInfo(void);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -77,6 +77,7 @@ struct SDL_Joystick
char *serial _guarded; /* Joystick serial */
SDL_JoystickGUID guid _guarded; /* Joystick guid */
Uint16 firmware_version _guarded; /* Firmware version, if available */
Uint64 steam_handle _guarded; /* Steam controller API handle */
int naxes _guarded; /* Number of axis controls on the joystick */
SDL_JoystickAxisInfo *axes _guarded;
@ -125,6 +126,8 @@ struct SDL_Joystick
struct joystick_hwdata *hwdata _guarded; /* Driver dependent information */
SDL_PropertiesID props _guarded;
int ref_count _guarded; /* Reference count for multiple opens */
struct SDL_Joystick *next _guarded; /* pointer to next joystick we have allocated */
@ -166,6 +169,9 @@ typedef struct SDL_JoystickDriver
/* Function to get the device-dependent path of a joystick */
const char *(*GetDevicePath)(int device_index);
/* Function to get the Steam virtual gamepad slot of a joystick */
int (*GetDeviceSteamVirtualGamepadSlot)(int device_index);
/* Function to get the player index of a joystick */
int (*GetDevicePlayerIndex)(int device_index);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -73,16 +73,16 @@ static int keycode_to_SDL(int keycode)
switch (keycode) {
/* Some gamepad buttons (API 9) */
case AKEYCODE_BUTTON_A:
button = SDL_GAMEPAD_BUTTON_A;
button = SDL_GAMEPAD_BUTTON_SOUTH;
break;
case AKEYCODE_BUTTON_B:
button = SDL_GAMEPAD_BUTTON_B;
button = SDL_GAMEPAD_BUTTON_EAST;
break;
case AKEYCODE_BUTTON_X:
button = SDL_GAMEPAD_BUTTON_X;
button = SDL_GAMEPAD_BUTTON_WEST;
break;
case AKEYCODE_BUTTON_Y:
button = SDL_GAMEPAD_BUTTON_Y;
button = SDL_GAMEPAD_BUTTON_NORTH;
break;
case AKEYCODE_BUTTON_L1:
button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER;
@ -136,7 +136,7 @@ static int keycode_to_SDL(int keycode)
case AKEYCODE_DPAD_CENTER:
/* This is handled better by applications as the A button */
/*button = 19;*/
button = SDL_GAMEPAD_BUTTON_A;
button = SDL_GAMEPAD_BUTTON_SOUTH;
break;
/* More gamepad buttons (API 12), these get mapped to 20...35*/
@ -174,9 +174,9 @@ static int keycode_to_SDL(int keycode)
static SDL_Scancode button_to_scancode(int button)
{
switch (button) {
case SDL_GAMEPAD_BUTTON_A:
case SDL_GAMEPAD_BUTTON_SOUTH:
return SDL_SCANCODE_RETURN;
case SDL_GAMEPAD_BUTTON_B:
case SDL_GAMEPAD_BUTTON_EAST:
return SDL_SCANCODE_ESCAPE;
case SDL_GAMEPAD_BUTTON_BACK:
return SDL_SCANCODE_ESCAPE;
@ -319,7 +319,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
}
}
if (JoystickByDeviceId(device_id) != NULL || name == NULL) {
if (JoystickByDeviceId(device_id) != NULL || !name) {
goto done;
}
@ -343,7 +343,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
nhats = 0;
}
guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, desc, 0, 0);
guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, NULL, desc, 0, 0);
/* Update the GUID with capability bits */
{
@ -353,7 +353,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
}
item = (SDL_joylist_item *)SDL_malloc(sizeof(SDL_joylist_item));
if (item == NULL) {
if (!item) {
goto done;
}
@ -361,7 +361,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
item->guid = guid;
item->device_id = device_id;
item->name = SDL_CreateJoystickName(vendor_id, product_id, NULL, name);
if (item->name == NULL) {
if (!item->name) {
SDL_free(item);
goto done;
}
@ -378,8 +378,8 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
}
item->naxes = naxes;
item->nhats = nhats;
item->device_instance = SDL_GetNextJoystickInstanceID();
if (SDL_joylist_tail == NULL) {
item->device_instance = SDL_GetNextObjectID();
if (!SDL_joylist_tail) {
SDL_joylist = SDL_joylist_tail = item;
} else {
SDL_joylist_tail->next = item;
@ -412,7 +412,7 @@ int Android_RemoveJoystick(int device_id)
SDL_LockJoysticks();
/* Don't call JoystickByDeviceId here or there'll be an infinite loop! */
while (item != NULL) {
while (item) {
if (item->device_id == device_id) {
break;
}
@ -420,7 +420,7 @@ int Android_RemoveJoystick(int device_id)
item = item->next;
}
if (item == NULL) {
if (!item) {
goto done;
}
@ -428,7 +428,7 @@ int Android_RemoveJoystick(int device_id)
item->joystick->hwdata = NULL;
}
if (prev != NULL) {
if (prev) {
prev->next = item->next;
} else {
SDL_assert(SDL_joylist == item);
@ -511,7 +511,7 @@ static SDL_joylist_item *JoystickByDeviceId(int device_id)
{
SDL_joylist_item *item = SDL_joylist;
while (item != NULL) {
while (item) {
if (item->device_id == device_id) {
return item;
}
@ -521,7 +521,7 @@ static SDL_joylist_item *JoystickByDeviceId(int device_id)
/* Joystick not found, try adding it */
ANDROID_JoystickDetect();
while (item != NULL) {
while (item) {
if (item->device_id == device_id) {
return item;
}
@ -541,6 +541,11 @@ static const char *ANDROID_JoystickGetDevicePath(int device_index)
return NULL;
}
static int ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int ANDROID_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -564,11 +569,11 @@ static int ANDROID_JoystickOpen(SDL_Joystick *joystick, int device_index)
{
SDL_joylist_item *item = GetJoystickByDevIndex(device_index);
if (item == NULL) {
if (!item) {
return SDL_SetError("No such device");
}
if (item->joystick != NULL) {
if (item->joystick) {
return SDL_SetError("Joystick already opened");
}
@ -616,7 +621,7 @@ static void ANDROID_JoystickUpdate(SDL_Joystick *joystick)
{
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
if (item == NULL) {
if (!item) {
return;
}
@ -681,6 +686,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = {
ANDROID_JoystickDetect,
ANDROID_JoystickGetDeviceName,
ANDROID_JoystickGetDevicePath,
ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot,
ANDROID_JoystickGetDevicePlayerIndex,
ANDROID_JoystickSetDevicePlayerIndex,
ANDROID_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -25,18 +25,18 @@
#include "../SDL_sysjoystick.h"
#include <CoreFoundation/CoreFoundation.h>
@class GCController;
typedef struct joystick_hwdata
{
SDL_bool accelerometer;
SDL_bool remote;
GCController __unsafe_unretained *controller;
void *rumble;
SDL_bool uses_pause_handler;
int num_pause_presses;
Uint32 pause_button_down_time;
int pause_button_index;
Uint64 pause_button_pressed;
char *name;
SDL_Joystick *joystick;
@ -47,9 +47,24 @@ typedef struct joystick_hwdata
int nbuttons;
int nhats;
Uint32 button_mask;
SDL_bool is_xbox;
SDL_bool is_ps4;
SDL_bool is_ps5;
SDL_bool is_switch_pro;
SDL_bool is_switch_joycon_pair;
SDL_bool is_switch_joyconL;
SDL_bool is_switch_joyconR;
SDL_bool is_stadia;
SDL_bool is_backbone_one;
int is_siri_remote;
NSArray *axes;
NSArray *buttons;
SDL_bool has_dualshock_touchpad;
SDL_bool has_xbox_paddles;
SDL_bool has_xbox_share_button;
SDL_bool has_nintendo_buttons;
struct joystick_hwdata *next;
} joystick_hwdata;

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -69,7 +69,7 @@
#include <sys/joystick.h>
#endif
#if SDL_HAVE_MACHINE_JOYSTICK_H
#ifdef SDL_HAVE_MACHINE_JOYSTICK_H
#include <machine/joystick.h>
#endif
@ -268,9 +268,8 @@ CreateHwData(const char *path)
hw = (struct joystick_hwdata *)
SDL_calloc(1, sizeof(struct joystick_hwdata));
if (hw == NULL) {
if (!hw) {
close(fd);
SDL_OutOfMemory();
return NULL;
}
hw->fd = fd;
@ -291,7 +290,7 @@ CreateHwData(const char *path)
}
}
hw->repdesc = hid_get_report_desc(fd);
if (hw->repdesc == NULL) {
if (!hw->repdesc) {
SDL_SetError("%s: USB_GET_REPORT_DESC: %s", path,
strerror(errno));
goto usberr;
@ -318,7 +317,7 @@ CreateHwData(const char *path)
#else
hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
#endif
if (hdata == NULL) {
if (!hdata) {
SDL_SetError("%s: Cannot start HID parser", path);
goto usberr;
}
@ -398,7 +397,7 @@ static int MaybeAddDevice(const char *path)
SDL_joylist_item *item;
struct joystick_hwdata *hw;
if (path == NULL) {
if (!path) {
return -1;
}
@ -407,14 +406,14 @@ static int MaybeAddDevice(const char *path)
}
/* Check to make sure it's not already in list. */
for (item = SDL_joylist; item != NULL; item = item->next) {
for (item = SDL_joylist; item; item = item->next) {
if (sb.st_rdev == item->devnum) {
return -1; /* already have this one */
}
}
hw = CreateHwData(path);
if (hw == NULL) {
if (!hw) {
return -1;
}
@ -426,7 +425,7 @@ static int MaybeAddDevice(const char *path)
struct usb_device_info di;
if (ioctl(hw->fd, USB_GET_DEVICEINFO, &di) != -1) {
name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product);
guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name, 0, 0);
guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, di.udi_vendor, di.udi_product, 0, 0);
#ifdef SDL_JOYSTICK_HIDAPI
if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) {
@ -444,14 +443,14 @@ static int MaybeAddDevice(const char *path)
}
#endif /* USB_GET_DEVICEINFO */
}
if (name == NULL) {
if (!name) {
name = SDL_strdup(path);
guid = SDL_CreateJoystickGUIDForName(name);
}
FreeHwData(hw);
item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item));
if (item == NULL) {
if (!item) {
SDL_free(name);
return -1;
}
@ -461,13 +460,13 @@ static int MaybeAddDevice(const char *path)
item->name = name;
item->guid = guid;
if ((item->path == NULL) || (item->name == NULL)) {
if ((!item->path) || (!item->name)) {
FreeJoylistItem(item);
return -1;
}
item->device_instance = SDL_GetNextJoystickInstanceID();
if (SDL_joylist_tail == NULL) {
item->device_instance = SDL_GetNextObjectID();
if (!SDL_joylist_tail) {
SDL_joylist = SDL_joylist_tail = item;
} else {
SDL_joylist_tail->next = item;
@ -544,6 +543,11 @@ static const char *BSD_JoystickGetDevicePath(int device_index)
return GetJoystickByDevIndex(device_index)->path;
}
static int BSD_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int BSD_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -583,12 +587,12 @@ static int BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
SDL_joylist_item *item = GetJoystickByDevIndex(device_index);
struct joystick_hwdata *hw;
if (item == NULL) {
if (!item) {
return SDL_SetError("No such device");
}
hw = CreateHwData(item->path);
if (hw == NULL) {
if (!hw) {
return -1;
}
@ -664,7 +668,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy)
#else
hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
#endif
if (hdata == NULL) {
if (!hdata) {
/*fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);*/
continue;
}
@ -694,7 +698,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy)
* calculate the SDL hat value from the 4 separate values.
*/
switch (usage) {
case HUG_DPAD_UP:
case HUG_DPAD_UP:
dpad[0] = (Sint32)hid_get_data(REP_BUF_DATA(rep), &hitem);
break;
case HUG_DPAD_DOWN:
@ -707,7 +711,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy)
dpad[3] = (Sint32)hid_get_data(REP_BUF_DATA(rep), &hitem);
break;
//default:
// no-op
// no-op
}
SDL_PrivateJoystickHat(joy, 0, (dpad[0] * HAT_UP) |
(dpad[1] * HAT_DOWN) |
@ -763,7 +767,7 @@ static int report_alloc(struct report *r, struct report_desc *rd, int repind)
#ifdef __DragonFly__
len = hid_report_size(rd, repinfo[repind].kind, r->rid);
#elif __FREEBSD__
#elif defined __FREEBSD__
#if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
#if (__FreeBSD_kernel_version <= 500111)
len = hid_report_size(rd, r->rid, repinfo[repind].kind);
@ -793,8 +797,8 @@ static int report_alloc(struct report *r, struct report_desc *rd, int repind)
r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) +
r->size);
#endif
if (r->buf == NULL) {
return SDL_OutOfMemory();
if (!r->buf) {
return -1;
}
} else {
r->buf = NULL;
@ -851,6 +855,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = {
BSD_JoystickDetect,
BSD_JoystickGetDeviceName,
BSD_JoystickGetDevicePath,
BSD_JoystickGetDeviceSteamVirtualGamepadSlot,
BSD_JoystickGetDevicePlayerIndex,
BSD_JoystickSetDevicePlayerIndex,
BSD_JoystickGetDeviceGUID,

View File

@ -66,7 +66,7 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x1a34, 0x0836 ), k_eControllerType_PS3Controller, NULL }, // Afterglow PS3
{ MAKE_CONTROLLER_ID( 0x20bc, 0x5500 ), k_eControllerType_PS3Controller, NULL }, // ShanWan PS3
{ MAKE_CONTROLLER_ID( 0x20d6, 0x576d ), k_eControllerType_PS3Controller, NULL }, // Power A PS3
{ MAKE_CONTROLLER_ID( 0x20d6, 0xca6d ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x20d6, 0xca6d ), k_eControllerType_PS3Controller, NULL }, // BDA Pro Ex
{ MAKE_CONTROLLER_ID( 0x2563, 0x0523 ), k_eControllerType_PS3Controller, NULL }, // Digiflip GP006
{ MAKE_CONTROLLER_ID( 0x2563, 0x0575 ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x25f0, 0x83c3 ), k_eControllerType_PS3Controller, NULL }, // gioteck vx2
@ -141,6 +141,8 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2303 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Obsidian Arcade Joystick
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2500 ), k_eControllerType_PS4Controller, NULL }, // Qanba Dragon
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2503 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Dragon Arcade Joystick
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d16 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution 5 Pro (PS4 mode with dongle)
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d17 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution 5 Pro (PS4 mode wired)
{ MAKE_CONTROLLER_ID( 0x7545, 0x0104 ), k_eControllerType_PS4Controller, NULL }, // Armor 3 or Level Up Cobra - At least one variant has gyro
{ MAKE_CONTROLLER_ID (0x9886, 0x0024 ), k_eControllerType_XInputPS4Controller, NULL }, // Astro C40 in Xbox 360 mode
{ MAKE_CONTROLLER_ID( 0x9886, 0x0025 ), k_eControllerType_PS4Controller, NULL }, // Astro C40
@ -149,11 +151,14 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x054c, 0x0ce6 ), k_eControllerType_PS5Controller, NULL }, // Sony DualSense Controller
{ MAKE_CONTROLLER_ID( 0x054c, 0x0df2 ), k_eControllerType_PS5Controller, NULL }, // Sony DualSense Edge Controller
{ MAKE_CONTROLLER_ID( 0x054c, 0x0e5f ), k_eControllerType_PS5Controller, NULL }, // Access Controller for PS5
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0209 ), k_eControllerType_PS5Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS5 mode)
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0163 ), k_eControllerType_PS5Controller, NULL }, // HORI Fighting Commander OCTA
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0184 ), k_eControllerType_PS5Controller, NULL }, // Hori Fighting Stick α
{ MAKE_CONTROLLER_ID( 0x1532, 0x100b ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wired)
{ MAKE_CONTROLLER_ID( 0x1532, 0x100c ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wireless)
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d18 ), k_eControllerType_PS5Controller, NULL }, // NACON Revolution 5 Pro (PS5 mode with dongle)
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d19 ), k_eControllerType_PS5Controller, NULL }, // NACON Revolution 5 Pro (PS5 mode wired)
{ MAKE_CONTROLLER_ID( 0x358a, 0x0104 ), k_eControllerType_PS5Controller, NULL }, // Backbone One PlayStation Edition for iOS
{ MAKE_CONTROLLER_ID( 0x0079, 0x0006 ), k_eControllerType_UnknownNonSteamController, NULL }, // DragonRise Generic USB PCB, sometimes configured as a PC Twin Shock Controller - looks like a DS3 but the face buttons are 1-4 instead of symbols
@ -161,13 +166,13 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x0079, 0x18d4 ), k_eControllerType_XBox360Controller, NULL }, // GPD Win 2 X-Box Controller
{ MAKE_CONTROLLER_ID( 0x03eb, 0xff02 ), k_eControllerType_XBox360Controller, NULL }, // Wooting Two
{ MAKE_CONTROLLER_ID( 0x044f, 0xb326 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster Gamepad GP XID
{ MAKE_CONTROLLER_ID( 0x045e, 0x028e ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad v2
{ MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (XBOX)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Big Button IR
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Wireless Controller with XUSB driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (third party knockoff)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver
{ MAKE_CONTROLLER_ID( 0x045e, 0x028e ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft Xbox 360 Wired Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft Xbox 360 Play and Charge Cable
{ MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // X-box 360 Wireless Receiver (third party knockoff)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft Xbox 360 Big Button IR
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Microsoft Xbox 360 Wireless Controller with XUSB driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // X-box 360 Wireless Receiver (third party knockoff)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Microsoft Xbox 360 Wireless Receiver
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21d ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F310
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21e ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F510
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21f ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F710
@ -296,24 +301,24 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafd ), k_eControllerType_XBox360Controller, NULL }, // Afterglow Gamepad 3
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafe ), k_eControllerType_XBox360Controller, NULL }, // Rock Candy Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x03f0, 0x0495 ), k_eControllerType_XBoxOneController, NULL }, // HP HyperX Clutch Gladiate
{ MAKE_CONTROLLER_ID( 0x044f, 0xd012 ), k_eControllerType_XBoxOneController, NULL }, // ThrustMaster eSwap PRO Controller Xbox
{ MAKE_CONTROLLER_ID( 0x045e, 0x02d1 ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x02dd ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad (Firmware 2015)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e0 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft X-Box One Elite pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad
{ 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" }, // The virtual keyboard generated by XboxGip drivers for Xbox One Controllers (see https://github.com/libsdl-org/SDL/pull/5121 for details)
{ 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 (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( 0x045e, 0x02d1 ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x02dd ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller (Firmware 2015)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e0 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft Xbox One Elite Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller with XBOXGIP driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0a ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0c ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft Xbox Series X Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft Xbox Series X Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b20 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b21 ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b22 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller (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
@ -566,7 +571,7 @@ static const ControllerDescription_t arrControllers[] = {
// The first two, at least, shouldn't have their buttons remapped, and since we
// can't tell which model we're actually using, we won't do any button remapping
// for any of them.
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00dc ), k_eControllerType_XInputSwitchController, NULL }, // HORIPAD S - Looks like a Switch controller but uses the Xbox 360 controller protocol
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00dc ), k_eControllerType_XInputSwitchController, NULL }, // HORIPAD S - Looks like a Switch controller but uses the Xbox 360 controller protocol, there is also a version of this that looks like a GameCube controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0180 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Pro Controller for Nintendo Switch
{ 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
@ -581,6 +586,7 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa714 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Spectra Controller
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa715 ), k_eControllerType_SwitchInputOnlyController, NULL }, // Power A Fusion Wireless Arcade Stick (USB Mode) Over BT is shows up as 057e 2009
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa716 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Fusion Pro Controller - USB requires toggling switch on back of device
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa718 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Nano Wired Controller
// Valve products
{ MAKE_CONTROLLER_ID( 0x0000, 0x11fb ), k_eControllerType_MobileTouch, NULL }, // Streaming mobile touch virtual controls
@ -588,7 +594,9 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x28de, 0x1102 ), k_eControllerType_SteamController, NULL }, // Valve wired Steam Controller (D0G)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1105 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1106 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G)
{ MAKE_CONTROLLER_ID( 0x28de, 0x11ff ), k_eControllerType_UnknownNonSteamController, "Steam Virtual Gamepad" }, // Steam virtual gamepad
{ MAKE_CONTROLLER_ID( 0x28de, 0x1142 ), k_eControllerType_SteamController, NULL }, // Valve wireless Steam Controller
{ MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1205 ), k_eControllerType_SteamControllerNeptune, NULL }, // Valve Steam Deck Builtin Controller
};

View File

@ -37,6 +37,7 @@ typedef enum
k_eControllerType_UnknownSteamController = 1,
k_eControllerType_SteamController = 2,
k_eControllerType_SteamControllerV2 = 3,
k_eControllerType_SteamControllerNeptune = 4,
// Other Controllers
k_eControllerType_UnknownNonSteamController = 30,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -40,7 +40,7 @@ static recDevice *gpDeviceList = NULL;
void FreeRumbleEffectData(FFEFFECT *effect)
{
if (effect == NULL) {
if (!effect) {
return;
}
SDL_free(effect->rgdwAxes);
@ -56,7 +56,7 @@ FFEFFECT *CreateRumbleEffectData(Sint16 magnitude)
/* Create the effect */
effect = (FFEFFECT *)SDL_calloc(1, sizeof(*effect));
if (effect == NULL) {
if (!effect) {
return NULL;
}
effect->dwSize = sizeof(*effect);
@ -80,7 +80,7 @@ FFEFFECT *CreateRumbleEffectData(Sint16 magnitude)
effect->dwFlags |= FFEFF_CARTESIAN;
periodic = (FFPERIODIC *)SDL_calloc(1, sizeof(*periodic));
if (periodic == NULL) {
if (!periodic) {
FreeRumbleEffectData(effect);
return NULL;
}
@ -405,6 +405,19 @@ static void AddHIDElement(const void *value, void *parameter)
}
}
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *product_string)
{
int slot = -1;
if (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER) {
/* Gamepad name is "GamePad-N", where N is slot + 1 */
if (SDL_sscanf(product_string, "GamePad-%d", &slot) == 1) {
slot -= 1;
}
}
return slot;
}
static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
{
Sint32 vendor = 0;
@ -484,7 +497,8 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
}
#endif
pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0);
pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0);
pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string);
array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);
if (array) {
@ -506,7 +520,7 @@ static SDL_bool JoystickAlreadyKnown(IOHIDDeviceRef ioHIDDeviceObject)
}
#endif
for (i = gpDeviceList; i != NULL; i = i->pNext) {
for (i = gpDeviceList; i; i = i->pNext) {
if (i->deviceRef == ioHIDDeviceObject) {
return SDL_TRUE;
}
@ -528,8 +542,7 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender
}
device = (recDevice *)SDL_calloc(1, sizeof(recDevice));
if (device == NULL) {
SDL_OutOfMemory();
if (!device) {
return;
}
@ -549,7 +562,7 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender
device->runLoopAttached = SDL_TRUE;
/* Allocate an instance ID for this device */
device->instance_id = SDL_GetNextJoystickInstanceID();
device->instance_id = SDL_GetNextObjectID();
/* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */
ioservice = IOHIDDeviceGetService(ioHIDDeviceObject);
@ -561,13 +574,13 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender
}
/* Add device to the end of the list */
if (gpDeviceList == NULL) {
if (!gpDeviceList) {
gpDeviceList = device;
} else {
recDevice *curdevice;
curdevice = gpDeviceList;
while (curdevice->pNext != NULL) {
while (curdevice->pNext) {
curdevice = curdevice->pNext;
}
curdevice->pNext = device;
@ -655,8 +668,8 @@ static SDL_bool CreateHIDManager(void)
static int DARWIN_JoystickInit(void)
{
if (gpDeviceList) {
return SDL_SetError("Joystick: Device list already inited.");
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_IOKIT, SDL_TRUE)) {
return 0;
}
if (!CreateHIDManager()) {
@ -692,10 +705,12 @@ static void DARWIN_JoystickDetect(void)
}
}
/* run this after the checks above so we don't set device->removed and delete the device before
DARWIN_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device */
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE, 0, TRUE) == kCFRunLoopRunHandledSource) {
/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
if (hidman) {
/* run this after the checks above so we don't set device->removed and delete the device before
DARWIN_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device */
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE, 0, TRUE) == kCFRunLoopRunHandledSource) {
/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
}
}
}
@ -710,6 +725,12 @@ const char *DARWIN_JoystickGetDevicePath(int device_index)
return NULL;
}
static int DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
recDevice *device = GetDeviceForIndex(device_index);
return device ? device->steam_virtual_gamepad_slot : -1;
}
static int DARWIN_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -832,7 +853,7 @@ static int DARWIN_JoystickInitRumble(recDevice *device, Sint16 magnitude)
/* Create the effect */
device->ffeffect = CreateRumbleEffectData(magnitude);
if (!device->ffeffect) {
return SDL_OutOfMemory();
return -1;
}
result = FFDeviceCreateEffect(device->ffdevice, kFFEffectType_Sine_ID,
@ -851,7 +872,7 @@ static int DARWIN_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_ru
/* Scale and average the two rumble strengths */
Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
if (device == NULL) {
if (!device) {
return SDL_SetError("Rumble failed, device disconnected");
}
@ -892,7 +913,7 @@ static Uint32 DARWIN_JoystickGetCapabilities(SDL_Joystick *joystick)
recDevice *device = joystick->hwdata;
Uint32 result = 0;
if (device == NULL) {
if (!device) {
return 0;
}
@ -926,7 +947,7 @@ static void DARWIN_JoystickUpdate(SDL_Joystick *joystick)
int i, goodRead = SDL_FALSE;
Uint64 timestamp = SDL_GetTicksNS();
if (device == NULL) {
if (!device) {
return;
}
@ -1055,6 +1076,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = {
DARWIN_JoystickDetect,
DARWIN_JoystickGetDeviceName,
DARWIN_JoystickGetDevicePath,
DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot,
DARWIN_JoystickGetDevicePlayerIndex,
DARWIN_JoystickSetDevicePlayerIndex,
DARWIN_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -71,6 +71,7 @@ struct joystick_hwdata
int instance_id;
SDL_JoystickGUID guid;
int steam_virtual_gamepad_slot;
struct joystick_hwdata *pNext; /* next device */
};

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -51,6 +51,11 @@ static const char *DUMMY_JoystickGetDevicePath(int device_index)
return NULL;
}
static int DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int DUMMY_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -130,6 +135,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = {
DUMMY_JoystickDetect,
DUMMY_JoystickGetDeviceName,
DUMMY_JoystickGetDevicePath,
DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot,
DUMMY_JoystickGetDevicePlayerIndex,
DUMMY_JoystickSetDevicePlayerIndex,
DUMMY_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -33,7 +33,6 @@ static SDL_joylist_item *JoystickByIndex(int index);
static SDL_joylist_item *SDL_joylist = NULL;
static SDL_joylist_item *SDL_joylist_tail = NULL;
static int numjoysticks = 0;
static int instance_counter = 0;
static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
{
@ -46,7 +45,7 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep
}
item = (SDL_joylist_item *)SDL_malloc(sizeof(SDL_joylist_item));
if (item == NULL) {
if (!item) {
return 1;
}
@ -54,13 +53,13 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep
item->index = gamepadEvent->index;
item->name = SDL_CreateJoystickName(0, 0, NULL, gamepadEvent->id);
if (item->name == NULL) {
if (!item->name) {
SDL_free(item);
return 1;
}
item->mapping = SDL_strdup(gamepadEvent->mapping);
if (item->mapping == NULL) {
if (!item->mapping) {
SDL_free(item->name);
SDL_free(item);
return 1;
@ -68,7 +67,7 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep
item->naxes = gamepadEvent->numAxes;
item->nbuttons = gamepadEvent->numButtons;
item->device_instance = instance_counter++;
item->device_instance = SDL_GetNextObjectID();
item->timestamp = gamepadEvent->timestamp;
@ -81,7 +80,7 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep
item->digitalButton[i] = gamepadEvent->digitalButton[i];
}
if (SDL_joylist_tail == NULL) {
if (!SDL_joylist_tail) {
SDL_joylist = SDL_joylist_tail = item;
} else {
SDL_joylist_tail->next = item;
@ -95,7 +94,6 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep
#ifdef DEBUG_JOYSTICK
SDL_Log("Number of joysticks is %d", numjoysticks);
#endif
#ifdef DEBUG_JOYSTICK
SDL_Log("Added joystick with index %d", item->index);
#endif
@ -108,7 +106,7 @@ static EM_BOOL Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGa
SDL_joylist_item *item = SDL_joylist;
SDL_joylist_item *prev = NULL;
while (item != NULL) {
while (item) {
if (item->index == gamepadEvent->index) {
break;
}
@ -116,7 +114,7 @@ static EM_BOOL Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGa
item = item->next;
}
if (item == NULL) {
if (!item) {
return 1;
}
@ -124,7 +122,7 @@ static EM_BOOL Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGa
item->joystick->hwdata = NULL;
}
if (prev != NULL) {
if (prev) {
prev->next = item->next;
} else {
SDL_assert(SDL_joylist == item);
@ -164,7 +162,6 @@ static void EMSCRIPTEN_JoystickQuit(void)
SDL_joylist = SDL_joylist_tail = NULL;
numjoysticks = 0;
instance_counter = 0;
emscripten_set_gamepadconnected_callback(NULL, 0, NULL);
emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL);
@ -243,7 +240,7 @@ static SDL_joylist_item *JoystickByIndex(int index)
return NULL;
}
while (item != NULL) {
while (item) {
if (item->index == index) {
break;
}
@ -272,6 +269,11 @@ static const char *EMSCRIPTEN_JoystickGetDevicePath(int device_index)
return NULL;
}
static int EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int EMSCRIPTEN_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -295,11 +297,11 @@ static int EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
{
SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
if (item == NULL) {
if (!item) {
return SDL_SetError("No such device");
}
if (item->joystick != NULL) {
if (item->joystick) {
return SDL_SetError("Joystick already opened");
}
@ -419,6 +421,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = {
EMSCRIPTEN_JoystickDetect,
EMSCRIPTEN_JoystickGetDeviceName,
EMSCRIPTEN_JoystickGetDevicePath,
EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot,
EMSCRIPTEN_JoystickGetDevicePlayerIndex,
EMSCRIPTEN_JoystickSetDevicePlayerIndex,
EMSCRIPTEN_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -101,6 +101,11 @@ extern "C"
return SDL_joyport[device_index];
}
static int HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int HAIKU_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -113,7 +118,7 @@ extern "C"
/* Function to perform the mapping from device index to the instance id for this index */
static SDL_JoystickID HAIKU_JoystickGetDeviceInstanceID(int device_index)
{
return device_index;
return device_index + 1;
}
static void HAIKU_JoystickClose(SDL_Joystick *joystick);
@ -129,12 +134,10 @@ extern "C"
/* Create the joystick data structure */
joystick->instance_id = device_index;
joystick->hwdata = (struct joystick_hwdata *)
SDL_malloc(sizeof(*joystick->hwdata));
joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata));
if (joystick->hwdata == NULL) {
return SDL_OutOfMemory();
return -1;
}
SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
stick = new BJoystick;
joystick->hwdata->stick = stick;
@ -152,13 +155,11 @@ extern "C"
joystick->naxes = stick->CountAxes();
joystick->nhats = stick->CountHats();
joystick->hwdata->new_axes = (int16 *)
SDL_malloc(joystick->naxes * sizeof(int16));
joystick->hwdata->new_hats = (uint8 *)
SDL_malloc(joystick->nhats * sizeof(uint8));
joystick->hwdata->new_axes = (int16 *) SDL_calloc(joystick->naxes, sizeof(int16));
joystick->hwdata->new_hats = (uint8 *) SDL_calloc(joystick->nhats, sizeof(uint8));
if (!joystick->hwdata->new_hats || !joystick->hwdata->new_axes) {
HAIKU_JoystickClose(joystick);
return SDL_OutOfMemory();
return -1;
}
/* We're done! */
@ -299,6 +300,7 @@ extern "C"
HAIKU_JoystickDetect,
HAIKU_JoystickGetDeviceName,
HAIKU_JoystickGetDevicePath,
HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot,
HAIKU_JoystickGetDevicePlayerIndex,
HAIKU_JoystickSetDevicePlayerIndex,
HAIKU_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -46,7 +46,6 @@ typedef struct
Uint8 rumble[1 + MAX_CONTROLLERS];
/* Without this variable, hid_write starts to lag a TON */
SDL_bool rumbleUpdate;
SDL_bool m_bUseButtonLabels;
SDL_bool useRumbleBrake;
} SDL_DriverGameCube_Context;
@ -73,7 +72,9 @@ static SDL_bool HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *devic
/* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */
return SDL_TRUE;
}
if (vendor_id == USB_VENDOR_DRAGONRISE && product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER) {
if (vendor_id == USB_VENDOR_DRAGONRISE &&
(product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 ||
product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2)) {
/* EVORETRO GameCube Controller Adapter */
return SDL_TRUE;
}
@ -90,12 +91,6 @@ static void ResetAxisRange(SDL_DriverGameCube_Context *ctx, int joystick_index)
ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_MAX + SDL_GAMEPAD_AXIS_RIGHT_TRIGGER] = 40;
}
static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
}
static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
if (hint) {
@ -104,22 +99,6 @@ static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, c
}
}
static Uint8 RemapButton(SDL_DriverGameCube_Context *ctx, Uint8 button)
{
if (!ctx->m_bUseButtonLabels) {
/* Use button positions */
switch (button) {
case SDL_GAMEPAD_BUTTON_B:
return SDL_GAMEPAD_BUTTON_X;
case SDL_GAMEPAD_BUTTON_X:
return SDL_GAMEPAD_BUTTON_B;
default:
break;
}
}
return button;
}
static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverGameCube_Context *ctx;
@ -135,8 +114,7 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
#endif
ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
device->context = ctx;
@ -203,8 +181,6 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
SDL_AddHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE,
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
@ -245,21 +221,21 @@ static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device
}
joystick = SDL_GetJoystickFromInstanceID(ctx->joysticks[i]);
if (joystick == NULL) {
if (!joystick) {
/* Hasn't been opened yet, skip */
return;
}
#define READ_BUTTON(off, flag, button) \
SDL_SendJoystickButton( \
SDL_SendJoystickButton( \
timestamp, \
joystick, \
RemapButton(ctx, button), \
button, \
(packet[off] & flag) ? SDL_PRESSED : SDL_RELEASED);
READ_BUTTON(1, 0x02, 0) /* A */
READ_BUTTON(1, 0x04, 1) /* B */
READ_BUTTON(1, 0x01, 2) /* X */
READ_BUTTON(1, 0x08, 3) /* Y */
READ_BUTTON(1, 0x01, 2) /* X */
READ_BUTTON(2, 0x80, 4) /* DPAD_LEFT */
READ_BUTTON(2, 0x20, 5) /* DPAD_RIGHT */
READ_BUTTON(2, 0x40, 6) /* DPAD_DOWN */
@ -286,8 +262,8 @@ static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device
joystick, \
axis, axis_value);
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0)
READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 0)
READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 1)
READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1)
READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0)
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1)
READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0)
READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0)
@ -322,7 +298,7 @@ static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device
joystick = SDL_GetJoystickFromInstanceID(ctx->joysticks[i]);
/* Hasn't been opened yet, skip */
if (joystick == NULL) {
if (!joystick) {
continue;
}
} else {
@ -334,14 +310,14 @@ static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device
}
#define READ_BUTTON(off, flag, button) \
SDL_SendJoystickButton( \
SDL_SendJoystickButton( \
timestamp, \
joystick, \
RemapButton(ctx, button), \
button, \
(curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED);
READ_BUTTON(1, 0x01, 0) /* A */
READ_BUTTON(1, 0x04, 1) /* B */
READ_BUTTON(1, 0x02, 2) /* X */
READ_BUTTON(1, 0x02, 1) /* B */
READ_BUTTON(1, 0x04, 2) /* X */
READ_BUTTON(1, 0x08, 3) /* Y */
READ_BUTTON(1, 0x10, 4) /* DPAD_LEFT */
READ_BUTTON(1, 0x20, 5) /* DPAD_RIGHT */
@ -386,7 +362,7 @@ static SDL_bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
/* Read input packet */
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);
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
#endif
if (ctx->pc_mode) {
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size);
@ -523,8 +499,6 @@ static void HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
SDL_DelHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE,
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -38,8 +38,8 @@
enum
{
SDL_CONTROLLER_BUTTON_LUNA_MIC = 15,
SDL_CONTROLLER_NUM_LUNA_BUTTONS,
SDL_GAMEPAD_BUTTON_LUNA_MICROPHONE = 11,
SDL_GAMEPAD_NUM_LUNA_BUTTONS,
};
typedef struct
@ -72,8 +72,7 @@ static SDL_bool HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverLuna_Context *ctx;
ctx = (SDL_DriverLuna_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
device->context = ctx;
@ -101,8 +100,9 @@ static SDL_bool HIDAPI_DriverLuna_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Jo
SDL_zeroa(ctx->last_state);
/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_CONTROLLER_NUM_LUNA_BUTTONS;
joystick->nbuttons = SDL_GAMEPAD_NUM_LUNA_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
return SDL_TRUE;
@ -169,10 +169,10 @@ static void HIDAPI_DriverLuna_HandleUSBStatePacket(SDL_Joystick *joystick, SDL_D
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[1] != data[1]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[1] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[1] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[1] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
@ -180,53 +180,44 @@ static void HIDAPI_DriverLuna_HandleUSBStatePacket(SDL_Joystick *joystick, SDL_D
}
if (ctx->last_state[2] != data[2]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_LUNA_MIC, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LUNA_MICROPHONE, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[3] != data[3]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[3] & 0xf) {
switch (data[3] & 0x0f) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
#define READ_STICK_AXIS(offset) \
@ -288,54 +279,45 @@ static void HIDAPI_DriverLuna_HandleBluetoothStatePacket(SDL_Joystick *joystick,
}
if (ctx->last_state[13] != data[13]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[13] & 0xf) {
switch (data[13] & 0x0f) {
case 1:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 2:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 3:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 4:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 5:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 6:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 7:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 8:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
if (ctx->last_state[14] != data[14]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
@ -346,7 +328,7 @@ static void HIDAPI_DriverLuna_HandleBluetoothStatePacket(SDL_Joystick *joystick,
}
if (ctx->last_state[16] != data[16]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_LUNA_MIC, (data[16] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LUNA_MICROPHONE, (data[16] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
}
#define READ_STICK_AXIS(offset) \
@ -393,7 +375,7 @@ static SDL_bool HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device)
#ifdef DEBUG_LUNA_PROTOCOL
HIDAPI_DumpPacket("Amazon Luna packet: size = %d", data, size);
#endif
if (joystick == NULL) {
if (!joystick) {
continue;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -134,8 +134,7 @@ static SDL_bool HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
}
ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -215,7 +214,7 @@ static void HIDAPI_DriverPS3_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL
{
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
if (ctx == NULL) {
if (!ctx) {
return;
}
@ -241,8 +240,9 @@ static SDL_bool HIDAPI_DriverPS3_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
ctx->player_index = SDL_GetJoystickPlayerIndex(joystick);
/* Initialize the joystick capabilities */
joystick->nbuttons = 15;
joystick->nbuttons = 11;
joystick->naxes = 16;
joystick->nhats = 1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f);
@ -315,52 +315,43 @@ static void HIDAPI_DriverPS3_HandleMiniStatePacket(SDL_Joystick *joystick, SDL_D
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[4] != data[4]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[4] & 0x0f) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[5] != data[5]) {
@ -392,23 +383,35 @@ static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_Drive
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[2] != data[2]) {
Uint8 hat = 0;
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
if (data[2] & 0x10) {
hat |= SDL_HAT_UP;
}
if (data[2] & 0x20) {
hat |= SDL_HAT_RIGHT;
}
if (data[2] & 0x40) {
hat |= SDL_HAT_DOWN;
}
if (data[2] & 0x80) {
hat |= SDL_HAT_LEFT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
if (ctx->last_state[3] != data[3]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[4] != data[4]) {
@ -431,10 +434,10 @@ static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_Drive
/* Buttons are mapped as axes in the order they appear in the button enumeration */
{
static int button_axis_offsets[] = {
24, /* SDL_GAMEPAD_BUTTON_A */
23, /* SDL_GAMEPAD_BUTTON_B */
25, /* SDL_GAMEPAD_BUTTON_X */
22, /* SDL_GAMEPAD_BUTTON_Y */
24, /* SDL_GAMEPAD_BUTTON_SOUTH */
23, /* SDL_GAMEPAD_BUTTON_EAST */
25, /* SDL_GAMEPAD_BUTTON_WEST */
22, /* SDL_GAMEPAD_BUTTON_NORTH */
0, /* SDL_GAMEPAD_BUTTON_BACK */
0, /* SDL_GAMEPAD_BUTTON_GUIDE */
0, /* SDL_GAMEPAD_BUTTON_START */
@ -491,7 +494,7 @@ static SDL_bool HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device)
#ifdef DEBUG_PS3_PROTOCOL
HIDAPI_DumpPacket("PS3 packet: size = %d", data, size);
#endif
if (joystick == NULL) {
if (!joystick) {
continue;
}
@ -604,8 +607,7 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverPS3_Context *ctx;
ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -641,8 +643,9 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_OpenJoystick(SDL_HIDAPI_Device *devic
SDL_zeroa(ctx->last_state);
/* Initialize the joystick capabilities */
joystick->nbuttons = 15;
joystick->nbuttons = 11;
joystick->naxes = 16;
joystick->nhats = 1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
return SDL_TRUE;
@ -684,19 +687,16 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystic
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[0] != data[0]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[1] != data[1]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
@ -705,40 +705,34 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystic
switch (data[1] >> 4) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
axis = ((int)data[16] * 257) - 32768;
@ -757,10 +751,10 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystic
/* Buttons are mapped as axes in the order they appear in the button enumeration */
{
static int button_axis_offsets[] = {
12, /* SDL_GAMEPAD_BUTTON_A */
11, /* SDL_GAMEPAD_BUTTON_B */
13, /* SDL_GAMEPAD_BUTTON_X */
10, /* SDL_GAMEPAD_BUTTON_Y */
12, /* SDL_GAMEPAD_BUTTON_SOUTH */
11, /* SDL_GAMEPAD_BUTTON_EAST */
13, /* SDL_GAMEPAD_BUTTON_WEST */
10, /* SDL_GAMEPAD_BUTTON_NORTH */
0, /* SDL_GAMEPAD_BUTTON_BACK */
0, /* SDL_GAMEPAD_BUTTON_GUIDE */
0, /* SDL_GAMEPAD_BUTTON_START */
@ -797,10 +791,10 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystic
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[0] != data[0]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[0] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[0] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}
@ -815,53 +809,55 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystic
if (ctx->device->vendor_id == USB_VENDOR_SAITEK && ctx->device->product_id == USB_PRODUCT_SAITEK_CYBORG_V3) {
/* Cyborg V.3 Rumble Pad doesn't set the dpad bits as expected, so use the axes instead */
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, data[10] ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, data[9] ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, data[7] ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, data[8] ? SDL_PRESSED : SDL_RELEASED);
Uint8 hat = 0;
if (data[7]) {
hat |= SDL_HAT_RIGHT;
}
if (data[8]) {
hat |= SDL_HAT_LEFT;
}
if (data[9]) {
hat |= SDL_HAT_UP;
}
if (data[10]) {
hat |= SDL_HAT_DOWN;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
} else {
if (ctx->last_state[2] != data[2]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[2] & 0x0f) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
}
@ -881,10 +877,10 @@ static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystic
/* Buttons are mapped as axes in the order they appear in the button enumeration */
{
static int button_axis_offsets[] = {
13, /* SDL_GAMEPAD_BUTTON_A */
12, /* SDL_GAMEPAD_BUTTON_B */
14, /* SDL_GAMEPAD_BUTTON_X */
11, /* SDL_GAMEPAD_BUTTON_Y */
13, /* SDL_GAMEPAD_BUTTON_SOUTH */
12, /* SDL_GAMEPAD_BUTTON_EAST */
14, /* SDL_GAMEPAD_BUTTON_WEST */
11, /* SDL_GAMEPAD_BUTTON_NORTH */
0, /* SDL_GAMEPAD_BUTTON_BACK */
0, /* SDL_GAMEPAD_BUTTON_GUIDE */
0, /* SDL_GAMEPAD_BUTTON_START */
@ -932,7 +928,7 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_UpdateDevice(SDL_HIDAPI_Device *devic
#ifdef DEBUG_PS3_PROTOCOL
HIDAPI_DumpPacket("PS3 packet: size = %d", data, size);
#endif
if (joystick == NULL) {
if (!joystick) {
continue;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -50,6 +50,11 @@
(((Uint32)(C)) << 16) | \
(((Uint32)(D)) << 24))
enum
{
SDL_GAMEPAD_BUTTON_PS4_TOUCHPAD = 11
};
typedef enum
{
k_EPS4ReportIdUsbState = 1,
@ -142,6 +147,7 @@ typedef struct
SDL_HIDAPI_Device *device;
SDL_Joystick *joystick;
SDL_bool is_dongle;
SDL_bool is_nacon_dongle;
SDL_bool official_controller;
SDL_bool sensors_supported;
SDL_bool lightbar_supported;
@ -275,8 +281,7 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
SDL_JoystickType joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD;
ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -413,6 +418,11 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
}
ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported);
if (device->vendor_id == USB_VENDOR_NACON_ALT &&
device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRELESS) {
ctx->is_nacon_dongle = SDL_TRUE;
}
if (device->vendor_id == USB_VENDOR_PDP &&
(device->product_id == USB_PRODUCT_VICTRIX_FS_PRO ||
device->product_id == USB_PRODUCT_VICTRIX_FS_PRO_V2)) {
@ -438,7 +448,7 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
} else {
HIDAPI_DisconnectBluetoothDevice(device->serial);
}
if (ctx->is_dongle && serial[0] == '\0') {
if ((ctx->is_dongle || ctx->is_nacon_dongle) && serial[0] == '\0') {
/* Not yet connected */
return SDL_TRUE;
}
@ -584,7 +594,7 @@ static SDL_bool HIDAPI_DriverPS4_LoadOfficialCalibrationData(SDL_HIDAPI_Device *
SDL_Log("calibration[%d] bias = %d, sensitivity = %f\n", i, ctx->calibration[i].bias, ctx->calibration[i].scale);
#endif
/* Some controllers have a bad calibration */
if (SDL_abs(ctx->calibration[i].bias) > 1024 || SDL_fabs(1.0f - ctx->calibration[i].scale) > 0.5f) {
if (SDL_abs(ctx->calibration[i].bias) > 1024 || SDL_fabsf(1.0f - ctx->calibration[i].scale) > 0.5f) {
#ifdef DEBUG_PS4_CALIBRATION
SDL_Log("invalid calibration, ignoring\n");
#endif
@ -685,10 +695,14 @@ static void HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data));
}
} else {
#if 0 /* The 8BitDo Zero 2 has perfect emulation of a PS4 controllers, except it
* only sends reports when the state changes, so we can't disconnect here.
*/
/* We can't even send an invalid effects packet, or it will put the controller in enhanced mode */
if (device->num_joysticks > 0) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}
#endif
}
}
@ -811,8 +825,12 @@ static SDL_bool HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
ctx->player_index = SDL_GetJoystickPlayerIndex(joystick);
/* Initialize the joystick capabilities */
joystick->nbuttons = ctx->touchpad_supported ? 16 : 15;
joystick->nbuttons = 11;
if (ctx->touchpad_supported) {
joystick->nbuttons += 1;
}
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
if (device->is_bluetooth) {
/* We'll update this once we're in enhanced mode */
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
@ -970,54 +988,45 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
{
Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
}
{
Uint8 hat;
Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
switch (data) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
}
@ -1045,7 +1054,7 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS4_TOUCHPAD, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
}
axis = ((int)packet->ucTriggerLeft * 257) - 32768;
@ -1131,7 +1140,7 @@ static SDL_bool VerifyCRC(Uint8 *data, int size)
packetCRC[1],
packetCRC[2],
packetCRC[3]);
return (unCRC == unPacketCRC) ? SDL_TRUE : SDL_FALSE;
return (unCRC == unPacketCRC);
}
static SDL_bool HIDAPI_DriverPS4_IsPacketValid(SDL_DriverPS4_Context *ctx, Uint8 *data, int size)
@ -1143,6 +1152,21 @@ static SDL_bool HIDAPI_DriverPS4_IsPacketValid(SDL_DriverPS4_Context *ctx, Uint8
return SDL_TRUE;
}
if (ctx->is_nacon_dongle && size >= (1 + sizeof(PS4StatePacket_t))) {
/* The report timestamp doesn't change when the controller isn't connected */
PS4StatePacket_t *packet = (PS4StatePacket_t *)&data[1];
if (SDL_memcmp(packet->rgucTimestamp, ctx->last_state.rgucTimestamp, sizeof(packet->rgucTimestamp)) == 0) {
return SDL_FALSE;
}
if (ctx->last_state.rgucAccelX[0] == 0 && ctx->last_state.rgucAccelX[1] == 0 &&
ctx->last_state.rgucAccelY[0] == 0 && ctx->last_state.rgucAccelY[1] == 0 &&
ctx->last_state.rgucAccelZ[0] == 0 && ctx->last_state.rgucAccelZ[1] == 0) {
/* We don't have any state to compare yet, go ahead and copy it */
SDL_memcpy(&ctx->last_state, &data[1], sizeof(PS4StatePacket_t));
return SDL_FALSE;
}
}
/* In the case of a DS4 USB dongle, bit[2] of byte 31 indicates if a DS4 is actually connected (indicated by '0').
* For non-dongle, this bit is always 0 (connected).
* This is usually the ID over USB, but the DS4v2 that started shipping with the PS4 Slim will also send this
@ -1207,7 +1231,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
++packet_count;
ctx->last_packet = now;
if (joystick == NULL) {
if (!joystick) {
continue;
}
@ -1254,7 +1278,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
}
}
if (ctx->is_dongle) {
if (ctx->is_dongle || ctx->is_nacon_dongle) {
if (packet_count == 0) {
if (device->num_joysticks > 0) {
/* Check to see if it looks like the device disconnected */
@ -1276,7 +1300,7 @@ static SDL_bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
}
}
if (size < 0 && device->num_joysticks > 0) {
if (packet_count == 0 && size < 0 && device->num_joysticks > 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -51,11 +51,12 @@
enum
{
SDL_CONTROLLER_BUTTON_PS5_TOUCHPAD = SDL_GAMEPAD_BUTTON_MISC1 + 1,
SDL_CONTROLLER_BUTTON_PS5_LEFT_FUNCTION,
SDL_CONTROLLER_BUTTON_PS5_RIGHT_FUNCTION,
SDL_CONTROLLER_BUTTON_PS5_LEFT_PADDLE,
SDL_CONTROLLER_BUTTON_PS5_RIGHT_PADDLE
SDL_GAMEPAD_BUTTON_PS5_TOUCHPAD = 11,
SDL_GAMEPAD_BUTTON_PS5_MICROPHONE,
SDL_GAMEPAD_BUTTON_PS5_LEFT_FUNCTION,
SDL_GAMEPAD_BUTTON_PS5_RIGHT_FUNCTION,
SDL_GAMEPAD_BUTTON_PS5_LEFT_PADDLE,
SDL_GAMEPAD_BUTTON_PS5_RIGHT_PADDLE
};
typedef enum
@ -231,6 +232,7 @@ typedef struct
{
SDL_HIDAPI_Device *device;
SDL_Joystick *joystick;
SDL_bool is_nacon_dongle;
SDL_bool use_alternate_report;
SDL_bool sensors_supported;
SDL_bool lightbar_supported;
@ -264,6 +266,7 @@ typedef struct
{
PS5SimpleStatePacket_t simple;
PS5StatePacketCommon_t state;
PS5StatePacketAlt_t alt_state;
PS5StatePacket_t full_state;
Uint8 data[64];
} last_state;
@ -351,7 +354,8 @@ static void SetLightsForPlayerIndex(DS5EffectsState_t *effects, int player_index
0x04,
0x0A,
0x15,
0x1B
0x1B,
0x1F
};
if (player_index >= 0) {
@ -372,8 +376,7 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
SDL_JoystickType joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD;
ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -490,10 +493,17 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
}
ctx->use_alternate_report = SDL_TRUE;
if (device->vendor_id == USB_VENDOR_NACON_ALT &&
(device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED ||
device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS)) {
/* This doesn't report vibration capability, but it can do rumble */
ctx->vibration_supported = SDL_TRUE;
}
} else if (device->vendor_id == USB_VENDOR_RAZER &&
(device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRED ||
device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRELESS)) {
/* The Razer Wolverine V2 Pro doesn't respond to the detection protocol, but has a touchpad and sensors, but no vibration */
/* The Razer Wolverine V2 Pro doesn't respond to the detection protocol, but has a touchpad and sensors and no vibration */
ctx->sensors_supported = SDL_TRUE;
ctx->touchpad_supported = SDL_TRUE;
ctx->use_alternate_report = SDL_TRUE;
@ -501,6 +511,11 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
}
ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported || ctx->playerled_supported);
if (device->vendor_id == USB_VENDOR_NACON_ALT &&
device->product_id == USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS) {
ctx->is_nacon_dongle = SDL_TRUE;
}
device->joystick_type = joystick_type;
device->type = SDL_GAMEPAD_TYPE_PS5;
if (device->vendor_id == USB_VENDOR_SONY) {
@ -512,6 +527,11 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
}
HIDAPI_SetDeviceSerial(device, serial);
if (ctx->is_nacon_dongle) {
/* We don't know if this is connected yet, wait for reports */
return SDL_TRUE;
}
/* Prefer the USB device over the Bluetooth device */
if (device->is_bluetooth) {
if (HIDAPI_HasConnectedUSBDevice(device->serial)) {
@ -610,7 +630,7 @@ static void HIDAPI_DriverPS5_LoadCalibrationData(SDL_HIDAPI_Device *device)
SDL_Log("calibration[%d] bias = %d, sensitivity = %f\n", i, ctx->calibration[i].bias, ctx->calibration[i].sensitivity);
#endif
/* Some controllers have a bad calibration */
if ((SDL_abs(ctx->calibration[i].bias) > 1024) || (SDL_fabs(1.0f - ctx->calibration[i].sensitivity / divisor) > 0.5f)) {
if ((SDL_abs(ctx->calibration[i].bias) > 1024) || (SDL_fabsf(1.0f - ctx->calibration[i].sensitivity / divisor) > 0.5f)) {
#ifdef DEBUG_PS5_CALIBRATION
SDL_Log("invalid calibration, ignoring\n");
#endif
@ -926,13 +946,14 @@ static SDL_bool HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
/* Initialize the joystick capabilities */
if (SDL_IsJoystickDualSenseEdge(device->vendor_id, device->product_id)) {
joystick->nbuttons = 21;
joystick->nbuttons = 17; /* paddles and touchpad and microphone */
} else if (ctx->touchpad_supported) {
joystick->nbuttons = 17;
joystick->nbuttons = 13; /* touchpad and microphone */
} else {
joystick->nbuttons = 15;
joystick->nbuttons = 11;
}
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
if (device->is_bluetooth) {
/* We'll update this once we're in enhanced mode */
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
@ -1113,54 +1134,45 @@ static void HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, SDL
{
Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
}
{
Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
}
@ -1179,7 +1191,7 @@ static void HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, SDL
Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_TOUCHPAD, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
}
if (packet->ucTriggerLeft == 0 && (packet->rgucButtonsHatAndCounter[1] & 0x04)) {
@ -1214,54 +1226,45 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL
{
Uint8 data = (packet->rgucButtonsAndHat[0] >> 4);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
}
{
Uint8 data = (packet->rgucButtonsAndHat[0] & 0x0F);
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
}
@ -1280,12 +1283,12 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL
Uint8 data = packet->rgucButtonsAndHat[2];
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_TOUCHPAD, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_LEFT_FUNCTION, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_RIGHT_FUNCTION, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_LEFT_PADDLE, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_PS5_RIGHT_PADDLE, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_TOUCHPAD, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_MICROPHONE, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_LEFT_FUNCTION, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_RIGHT_FUNCTION, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_LEFT_PADDLE, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_PS5_RIGHT_PADDLE, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (packet->ucTriggerLeft == 0 && (packet->rgucButtonsAndHat[1] & 0x04)) {
@ -1429,13 +1432,27 @@ static SDL_bool VerifyCRC(Uint8 *data, int size)
packetCRC[1],
packetCRC[2],
packetCRC[3]);
return (unCRC == unPacketCRC) ? SDL_TRUE : SDL_FALSE;
return (unCRC == unPacketCRC);
}
static SDL_bool HIDAPI_DriverPS5_IsPacketValid(SDL_DriverPS5_Context *ctx, Uint8 *data, int size)
{
switch (data[0]) {
case k_EPS5ReportIdState:
if (ctx->is_nacon_dongle && size >= (1 + sizeof(PS5StatePacketAlt_t))) {
/* The report timestamp doesn't change when the controller isn't connected */
PS5StatePacketAlt_t *packet = (PS5StatePacketAlt_t *)&data[1];
if (SDL_memcmp(packet->rgucPacketSequence, ctx->last_state.state.rgucPacketSequence, sizeof(packet->rgucPacketSequence)) == 0) {
return SDL_FALSE;
}
if (ctx->last_state.alt_state.rgucAccelX[0] == 0 && ctx->last_state.alt_state.rgucAccelX[1] == 0 &&
ctx->last_state.alt_state.rgucAccelY[0] == 0 && ctx->last_state.alt_state.rgucAccelY[1] == 0 &&
ctx->last_state.alt_state.rgucAccelZ[0] == 0 && ctx->last_state.alt_state.rgucAccelZ[1] == 0) {
/* We don't have any state to compare yet, go ahead and copy it */
SDL_memcpy(&ctx->last_state, &data[1], sizeof(PS5StatePacketAlt_t));
return SDL_FALSE;
}
}
return SDL_TRUE;
case k_EPS5ReportIdBluetoothState:
@ -1475,7 +1492,7 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
++packet_count;
ctx->last_packet = now;
if (joystick == NULL) {
if (!joystick) {
continue;
}
@ -1530,7 +1547,22 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
}
}
if (size < 0 && device->num_joysticks > 0) {
if (ctx->is_nacon_dongle) {
if (packet_count == 0) {
if (device->num_joysticks > 0) {
/* Check to see if it looks like the device disconnected */
if (now >= (ctx->last_packet + BLUETOOTH_DISCONNECT_TIMEOUT_MS)) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}
}
} else {
if (device->num_joysticks == 0) {
HIDAPI_JoystickConnected(device, NULL);
}
}
}
if (packet_count == 0 && size < 0 && device->num_joysticks > 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -214,9 +214,9 @@ int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const
}
request = (SDL_HIDAPI_RumbleRequest *)SDL_calloc(1, sizeof(*request));
if (request == NULL) {
if (!request) {
SDL_HIDAPI_UnlockRumble();
return SDL_OutOfMemory();
return -1;
}
request->device = device;
SDL_memcpy(request->data, data, size);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -46,12 +46,13 @@
enum
{
SDL_CONTROLLER_BUTTON_SHIELD_V103_TOUCHPAD = SDL_GAMEPAD_BUTTON_MISC1 + 1,
SDL_CONTROLLER_BUTTON_SHIELD_V103_MINUS,
SDL_CONTROLLER_BUTTON_SHIELD_V103_PLUS,
SDL_CONTROLLER_NUM_SHIELD_V103_BUTTONS,
SDL_GAMEPAD_BUTTON_SHIELD_SHARE = 11,
SDL_GAMEPAD_BUTTON_SHIELD_V103_TOUCHPAD,
SDL_GAMEPAD_BUTTON_SHIELD_V103_MINUS,
SDL_GAMEPAD_BUTTON_SHIELD_V103_PLUS,
SDL_GAMEPAD_NUM_SHIELD_V103_BUTTONS,
SDL_CONTROLLER_NUM_SHIELD_V104_BUTTONS = SDL_GAMEPAD_BUTTON_MISC1 + 1,
SDL_GAMEPAD_NUM_SHIELD_V104_BUTTONS = SDL_GAMEPAD_BUTTON_SHIELD_SHARE + 1,
};
typedef enum
@ -114,8 +115,7 @@ static SDL_bool HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverShield_Context *ctx;
ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
device->context = ctx;
@ -181,14 +181,16 @@ static SDL_bool HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
/* Initialize the joystick capabilities */
if (device->product_id == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V103) {
joystick->nbuttons = SDL_CONTROLLER_NUM_SHIELD_V103_BUTTONS;
joystick->nbuttons = SDL_GAMEPAD_NUM_SHIELD_V103_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
SDL_PrivateJoystickAddTouchpad(joystick, 1);
} else {
joystick->nbuttons = SDL_CONTROLLER_NUM_SHIELD_V104_BUTTONS;
joystick->nbuttons = SDL_GAMEPAD_NUM_SHIELD_V104_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
}
@ -289,54 +291,45 @@ static void HIDAPI_DriverShield_HandleStatePacketV103(SDL_Joystick *joystick, SD
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[3] != data[3]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[3]) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
if (ctx->last_state[1] != data[1]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[1] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[1] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[1] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
@ -345,11 +338,11 @@ static void HIDAPI_DriverShield_HandleStatePacketV103(SDL_Joystick *joystick, SD
if (ctx->last_state[2] != data[2]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_SHIELD_V103_PLUS, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_SHIELD_V103_MINUS, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_V103_PLUS, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_V103_MINUS, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_SHARE, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, SDL_SwapLE16(*(Sint16 *)&data[4]) - 0x8000);
@ -373,7 +366,7 @@ static void HIDAPI_DriverShield_HandleTouchPacketV103(SDL_Joystick *joystick, SD
float touchpad_x, touchpad_y;
Uint64 timestamp = SDL_GetTicksNS();
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_SHIELD_V103_TOUCHPAD, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_V103_TOUCHPAD, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
/* It's a triangular pad, but just use the center as the usable touch area */
touchpad_state = !(data[1] & 0x80) ? SDL_PRESSED : SDL_RELEASED;
@ -391,54 +384,45 @@ static void HIDAPI_DriverShield_HandleStatePacketV104(SDL_Joystick *joystick, SD
}
if (ctx->last_state[2] != data[2]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[2]) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
if (ctx->last_state[3] != data[3]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
@ -459,7 +443,7 @@ static void HIDAPI_DriverShield_HandleStatePacketV104(SDL_Joystick *joystick, SD
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, SDL_SwapLE16(*(Sint16 *)&data[21]) - 0x8000);
if (ctx->last_state[17] != data[17]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[17] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SHIELD_SHARE, (data[17] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[17] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[17] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
}
@ -489,7 +473,7 @@ static SDL_bool HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device)
/* Byte 0 is HID report ID */
switch (data[0]) {
case k_ShieldReportIdControllerState:
if (joystick == NULL) {
if (!joystick) {
break;
}
if (size == 16) {
@ -499,7 +483,7 @@ static SDL_bool HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device)
}
break;
case k_ShieldReportIdControllerTouch:
if (joystick == NULL) {
if (!joystick) {
break;
}
HIDAPI_DriverShield_HandleTouchPacketV103(joystick, ctx, data, size);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -33,9 +33,9 @@
enum
{
SDL_CONTROLLER_BUTTON_STADIA_SHARE = 15,
SDL_CONTROLLER_BUTTON_STADIA_GOOGLE_ASSISTANT,
SDL_CONTROLLER_NUM_STADIA_BUTTONS,
SDL_GAMEPAD_BUTTON_STADIA_SHARE = 11,
SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT,
SDL_GAMEPAD_NUM_STADIA_BUTTONS,
};
typedef struct
@ -69,8 +69,7 @@ static SDL_bool HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverStadia_Context *ctx;
ctx = (SDL_DriverStadia_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
device->context = ctx;
@ -107,8 +106,9 @@ static SDL_bool HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
SDL_zeroa(ctx->last_state);
/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_CONTROLLER_NUM_STADIA_BUTTONS;
joystick->nbuttons = SDL_GAMEPAD_NUM_STADIA_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
return SDL_TRUE;
@ -179,47 +179,38 @@ static void HIDAPI_DriverStadia_HandleStatePacket(SDL_Joystick *joystick, SDL_Dr
}
if (ctx->last_state[1] != data[1]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[1]) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
if (ctx->last_state[2] != data[2]) {
@ -227,15 +218,15 @@ static void HIDAPI_DriverStadia_HandleStatePacket(SDL_Joystick *joystick, SDL_Dr
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_STADIA_SHARE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_CONTROLLER_BUTTON_STADIA_GOOGLE_ASSISTANT, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_SHARE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[3] != data[3]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
@ -285,7 +276,7 @@ static SDL_bool HIDAPI_DriverStadia_UpdateDevice(SDL_HIDAPI_Device *device)
#ifdef DEBUG_STADIA_PROTOCOL
HIDAPI_DumpPacket("Google Stadia packet: size = %d", data, size);
#endif
if (joystick == NULL) {
if (!joystick) {
continue;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -29,29 +29,31 @@
/*****************************************************************************************************/
#include <stdint.h>
#define bool SDL_bool
#define true SDL_TRUE
#define false SDL_FALSE
typedef uint32_t uint32;
typedef uint64_t uint64;
#include "steam/controller_constants.h"
#include "steam/controller_structs.h"
enum
{
SDL_GAMEPAD_BUTTON_STEAM_RIGHT_PADDLE = 11,
SDL_GAMEPAD_BUTTON_STEAM_LEFT_PADDLE,
SDL_GAMEPAD_NUM_STEAM_BUTTONS,
};
typedef struct SteamControllerStateInternal_t
{
// Controller Type for this Controller State
uint32 eControllerType;
Uint32 eControllerType;
// If packet num matches that on your prior call, then the controller state hasn't been changed since
// your last call and there is no need to process it
uint32 unPacketNum;
Uint32 unPacketNum;
// bit flags for each of the buttons
uint64 ulButtons;
Uint64 ulButtons;
// Left pad coordinates
short sLeftPadX;
@ -973,8 +975,7 @@ static SDL_bool HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverSteam_Context *ctx;
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
device->context = ctx;
@ -1024,8 +1025,9 @@ static SDL_bool HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_J
InitializeSteamControllerPacketAssembler(&ctx->m_assembler);
/* Initialize the joystick capabilities */
joystick->nbuttons = 17;
joystick->nbuttons = SDL_GAMEPAD_NUM_STEAM_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz);
@ -1070,9 +1072,9 @@ static int HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_J
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 */);
ADD_SETTING(SETTING_IMU_MODE, SETTING_GYRO_MODE_SEND_RAW_ACCEL | SETTING_GYRO_MODE_SEND_RAW_GYRO);
} else {
ADD_SETTING(SETTING_GYRO_MODE, 0x00 /* SETTING_GYRO_MODE_OFF */);
ADD_SETTING(SETTING_IMU_MODE, SETTING_GYRO_MODE_OFF);
}
buf[2] = (unsigned char)(nSettings * 3);
if (SetFeatureReport(device->dev, buf, 3 + nSettings * 3) < 0) {
@ -1105,7 +1107,7 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
break;
}
if (joystick == NULL) {
if (!joystick) {
continue;
}
@ -1120,16 +1122,18 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->m_state.ulButtons != ctx->m_last_state.ulButtons) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A,
Uint8 hat = 0;
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH,
(ctx->m_state.ulButtons & STEAM_BUTTON_3_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B,
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST,
(ctx->m_state.ulButtons & STEAM_BUTTON_1_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X,
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST,
(ctx->m_state.ulButtons & STEAM_BUTTON_2_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y,
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH,
(ctx->m_state.ulButtons & STEAM_BUTTON_0_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER,
@ -1149,19 +1153,24 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK,
(ctx->m_state.ulButtons & STEAM_JOYSTICK_BUTTON_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1 + 0,
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_LEFT_PADDLE,
(ctx->m_state.ulButtons & STEAM_BUTTON_BACK_LEFT_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1 + 1,
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_RIGHT_PADDLE,
(ctx->m_state.ulButtons & STEAM_BUTTON_BACK_RIGHT_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP,
(ctx->m_state.ulButtons & STEAM_TOUCH_0_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN,
(ctx->m_state.ulButtons & STEAM_TOUCH_3_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT,
(ctx->m_state.ulButtons & STEAM_TOUCH_2_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT,
(ctx->m_state.ulButtons & STEAM_TOUCH_1_MASK) ? SDL_PRESSED : SDL_RELEASED);
if (ctx->m_state.ulButtons & STEAM_TOUCH_0_MASK) {
hat |= SDL_HAT_UP;
}
if (ctx->m_state.ulButtons & STEAM_TOUCH_3_MASK) {
hat |= SDL_HAT_DOWN;
}
if (ctx->m_state.ulButtons & STEAM_TOUCH_2_MASK) {
hat |= SDL_HAT_LEFT;
}
if (ctx->m_state.ulButtons & STEAM_TOUCH_1_MASK) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (int)ctx->m_state.sTriggerL * 2 - 32768);

View File

@ -0,0 +1,443 @@
/*
Simple DirectMedia Layer
Copyright (C) 2023 Max Maisel <max.maisel@posteo.de>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifdef SDL_JOYSTICK_HIDAPI
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK
/*****************************************************************************************************/
#include "steam/controller_constants.h"
#include "steam/controller_structs.h"
enum
{
SDL_GAMEPAD_BUTTON_STEAM_DECK_QAM = 11,
SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE1,
SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE1,
SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE2,
SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE2,
SDL_GAMEPAD_NUM_STEAM_DECK_BUTTONS,
};
typedef enum
{
STEAMDECK_LBUTTON_R2 = 0x00000001,
STEAMDECK_LBUTTON_L2 = 0x00000002,
STEAMDECK_LBUTTON_R = 0x00000004,
STEAMDECK_LBUTTON_L = 0x00000008,
STEAMDECK_LBUTTON_Y = 0x00000010,
STEAMDECK_LBUTTON_B = 0x00000020,
STEAMDECK_LBUTTON_X = 0x00000040,
STEAMDECK_LBUTTON_A = 0x00000080,
STEAMDECK_LBUTTON_DPAD_UP = 0x00000100,
STEAMDECK_LBUTTON_DPAD_RIGHT = 0x00000200,
STEAMDECK_LBUTTON_DPAD_LEFT = 0x00000400,
STEAMDECK_LBUTTON_DPAD_DOWN = 0x00000800,
STEAMDECK_LBUTTON_VIEW = 0x00001000,
STEAMDECK_LBUTTON_STEAM = 0x00002000,
STEAMDECK_LBUTTON_MENU = 0x00004000,
STEAMDECK_LBUTTON_L5 = 0x00008000,
STEAMDECK_LBUTTON_R5 = 0x00010000,
STEAMDECK_LBUTTON_LEFT_PAD = 0x00020000,
STEAMDECK_LBUTTON_RIGHT_PAD = 0x00040000,
STEAMDECK_LBUTTON_L3 = 0x00400000,
STEAMDECK_LBUTTON_R3 = 0x04000000,
STEAMDECK_HBUTTON_L4 = 0x00000200,
STEAMDECK_HBUTTON_R4 = 0x00000400,
STEAMDECK_HBUTTON_QAM = 0x00040000,
} SteamDeckButtons;
typedef struct
{
Uint32 update_rate_us;
Uint32 sensor_timestamp_us;
Uint64 last_button_state;
Uint8 watchdog_counter;
} SDL_DriverSteamDeck_Context;
static SDL_bool DisableDeckLizardMode(SDL_hid_device *dev)
{
int rc;
Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 };
FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1);
msg->header.type = ID_CLEAR_DIGITAL_MAPPINGS;
rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer));
if (rc != sizeof(buffer))
return SDL_FALSE;
msg->header.type = ID_SET_SETTINGS_VALUES;
msg->header.length = 5 * sizeof(ControllerSetting);
msg->payload.setSettingsValues.settings[0].settingNum = SETTING_SMOOTH_ABSOLUTE_MOUSE;
msg->payload.setSettingsValues.settings[0].settingValue = 0;
msg->payload.setSettingsValues.settings[1].settingNum = SETTING_LEFT_TRACKPAD_MODE;
msg->payload.setSettingsValues.settings[1].settingValue = TRACKPAD_NONE;
msg->payload.setSettingsValues.settings[2].settingNum = SETTING_RIGHT_TRACKPAD_MODE; // disable mouse
msg->payload.setSettingsValues.settings[2].settingValue = TRACKPAD_NONE;
msg->payload.setSettingsValues.settings[3].settingNum = SETTING_LEFT_TRACKPAD_CLICK_PRESSURE; // disable clicky pad
msg->payload.setSettingsValues.settings[3].settingValue = 0xFFFF;
msg->payload.setSettingsValues.settings[4].settingNum = SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE; // disable clicky pad
msg->payload.setSettingsValues.settings[4].settingValue = 0xFFFF;
rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer));
if (rc != sizeof(buffer))
return SDL_FALSE;
// There may be a lingering report read back after changing settings.
// Discard it.
SDL_hid_get_feature_report(dev, buffer, sizeof(buffer));
return SDL_TRUE;
}
static SDL_bool FeedDeckLizardWatchdog(SDL_hid_device *dev)
{
int rc;
Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 };
FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1);
msg->header.type = ID_CLEAR_DIGITAL_MAPPINGS;
rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer));
if (rc != sizeof(buffer))
return SDL_FALSE;
msg->header.type = ID_SET_SETTINGS_VALUES;
msg->header.length = 1 * sizeof(ControllerSetting);
msg->payload.setSettingsValues.settings[0].settingNum = SETTING_RIGHT_TRACKPAD_MODE;
msg->payload.setSettingsValues.settings[0].settingValue = TRACKPAD_NONE;
rc = SDL_hid_send_feature_report(dev, buffer, sizeof(buffer));
if (rc != sizeof(buffer))
return SDL_FALSE;
// There may be a lingering report read back after changing settings.
// Discard it.
SDL_hid_get_feature_report(dev, buffer, sizeof(buffer));
return SDL_TRUE;
}
/*****************************************************************************************************/
static void HIDAPI_DriverSteamDeck_RegisterHints(SDL_HintCallback callback, void *userdata)
{
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata);
}
static void HIDAPI_DriverSteamDeck_UnregisterHints(SDL_HintCallback callback, void *userdata)
{
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata);
}
static SDL_bool HIDAPI_DriverSteamDeck_IsEnabled(void)
{
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK,
SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT));
}
static SDL_bool HIDAPI_DriverSteamDeck_IsSupportedDevice(
SDL_HIDAPI_Device *device,
const char *name,
SDL_GamepadType type,
Uint16 vendor_id,
Uint16 product_id,
Uint16 version,
int interface_number,
int interface_class,
int interface_subclass,
int interface_protocol)
{
return SDL_IsJoystickSteamDeck(vendor_id, product_id);
}
static SDL_bool HIDAPI_DriverSteamDeck_InitDevice(SDL_HIDAPI_Device *device)
{
int size;
Uint8 data[64];
SDL_DriverSteamDeck_Context *ctx;
ctx = (SDL_DriverSteamDeck_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
return SDL_FALSE;
}
// Always 1kHz according to USB descriptor
ctx->update_rate_us = 1000;
device->context = ctx;
// Read a report to see if this is the correct endpoint.
// Mouse, Keyboard and Controller have the same VID/PID but
// only the controller hidraw device receives hid reports.
size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16);
if (size == 0)
return SDL_FALSE;
if (!DisableDeckLizardMode(device->dev))
return SDL_FALSE;
HIDAPI_SetDeviceName(device, "Steam Deck");
return HIDAPI_JoystickConnected(device, NULL);
}
static int HIDAPI_DriverSteamDeck_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
{
return -1;
}
static void HIDAPI_DriverSteamDeck_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
{
}
static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverSteamDeck_Context *ctx = (SDL_DriverSteamDeck_Context *)device->context;
SDL_Joystick *joystick = NULL;
int r;
uint8_t data[64];
float values[3];
ValveInReport_t *pInReport = (ValveInReport_t *)data;
if (device->num_joysticks > 0) {
joystick = SDL_GetJoystickFromInstanceID(device->joysticks[0]);
if (joystick == NULL) {
return SDL_FALSE;
}
} else {
return SDL_FALSE;
}
if (ctx->watchdog_counter++ > 200) {
ctx->watchdog_counter = 0;
if (!FeedDeckLizardWatchdog(device->dev))
return SDL_FALSE;
}
SDL_memset(data, 0, sizeof(data));
r = SDL_hid_read(device->dev, data, sizeof(data));
if (r == 0) {
return SDL_FALSE;
} else if (r <= 0) {
/* Failed to read from controller */
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
return SDL_FALSE;
}
if (!(r == 64 && pInReport->header.unReportVersion == k_ValveInReportMsgVersion && pInReport->header.ucType == ID_CONTROLLER_DECK_STATE && pInReport->header.ucLength == 64)) {
return SDL_FALSE;
}
Uint64 timestamp = SDL_GetTicksNS();
if (pInReport->payload.deckState.ulButtons != ctx->last_button_state) {
Uint8 hat = 0;
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_A) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_B) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_X) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_Y) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_VIEW) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_MENU) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_STEAM) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_QAM,
(pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_QAM) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L3) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R3) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE1,
(pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_R4) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE1,
(pInReport->payload.deckState.ulButtonsH & STEAMDECK_HBUTTON_L4) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_RIGHT_PADDLE2,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_R5) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_DECK_LEFT_PADDLE2,
(pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_L5) ? SDL_PRESSED : SDL_RELEASED);
if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_UP) {
hat |= SDL_HAT_UP;
}
if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_DOWN) {
hat |= SDL_HAT_DOWN;
}
if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_LEFT) {
hat |= SDL_HAT_LEFT;
}
if (pInReport->payload.deckState.ulButtonsL & STEAMDECK_LBUTTON_DPAD_RIGHT) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
ctx->last_button_state = pInReport->payload.deckState.ulButtons;
}
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER,
(int)pInReport->payload.deckState.sTriggerRawL * 2 - 32768);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER,
(int)pInReport->payload.deckState.sTriggerRawR * 2 - 32768);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX,
pInReport->payload.deckState.sLeftStickX);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY,
-pInReport->payload.deckState.sLeftStickY);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX,
pInReport->payload.deckState.sRightStickX);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY,
-pInReport->payload.deckState.sRightStickY);
ctx->sensor_timestamp_us += ctx->update_rate_us;
values[0] = (pInReport->payload.deckState.sGyroX / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f));
values[1] = (pInReport->payload.deckState.sGyroZ / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f));
values[2] = (-pInReport->payload.deckState.sGyroY / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f));
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, ctx->sensor_timestamp_us, values, 3);
values[0] = (pInReport->payload.deckState.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
values[1] = (pInReport->payload.deckState.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
values[2] = (-pInReport->payload.deckState.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, ctx->sensor_timestamp_us, values, 3);
return SDL_TRUE;
}
static SDL_bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
SDL_DriverSteamDeck_Context *ctx = (SDL_DriverSteamDeck_Context *)device->context;
float update_rate_in_hz = 1.0f / (float)(ctx->update_rate_us) * 1.0e6f;
SDL_AssertJoysticksLocked();
// Initialize the joystick capabilities
joystick->nbuttons = SDL_GAMEPAD_NUM_STEAM_DECK_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz);
return SDL_TRUE;
}
static int HIDAPI_DriverSteamDeck_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
int rc;
Uint8 buffer[HID_FEATURE_REPORT_BYTES + 1] = { 0 };
FeatureReportMsg *msg = (FeatureReportMsg *)(buffer + 1);
msg->header.type = ID_TRIGGER_RUMBLE_CMD;
msg->payload.simpleRumble.unRumbleType = 0;
msg->payload.simpleRumble.unIntensity = HAPTIC_INTENSITY_SYSTEM;
msg->payload.simpleRumble.unLeftMotorSpeed = low_frequency_rumble;
msg->payload.simpleRumble.unRightMotorSpeed = high_frequency_rumble;
msg->payload.simpleRumble.nLeftGain = 2;
msg->payload.simpleRumble.nRightGain = 0;
rc = SDL_hid_send_feature_report(device->dev, buffer, sizeof(buffer));
if (rc != sizeof(buffer))
return -1;
return 0;
}
static int HIDAPI_DriverSteamDeck_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{
return SDL_Unsupported();
}
static Uint32 HIDAPI_DriverSteamDeck_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_JOYCAP_RUMBLE;
}
static int HIDAPI_DriverSteamDeck_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static int HIDAPI_DriverSteamDeck_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
{
return SDL_Unsupported();
}
static int HIDAPI_DriverSteamDeck_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
// On steam deck, sensors are enabled by default. Nothing to do here.
return 0;
}
static void HIDAPI_DriverSteamDeck_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
// Lizard mode id automatically re-enabled by watchdog. Nothing to do here.
}
static void HIDAPI_DriverSteamDeck_FreeDevice(SDL_HIDAPI_Device *device)
{
}
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamDeck = {
SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK,
SDL_TRUE,
HIDAPI_DriverSteamDeck_RegisterHints,
HIDAPI_DriverSteamDeck_UnregisterHints,
HIDAPI_DriverSteamDeck_IsEnabled,
HIDAPI_DriverSteamDeck_IsSupportedDevice,
HIDAPI_DriverSteamDeck_InitDevice,
HIDAPI_DriverSteamDeck_GetDevicePlayerIndex,
HIDAPI_DriverSteamDeck_SetDevicePlayerIndex,
HIDAPI_DriverSteamDeck_UpdateDevice,
HIDAPI_DriverSteamDeck_OpenJoystick,
HIDAPI_DriverSteamDeck_RumbleJoystick,
HIDAPI_DriverSteamDeck_RumbleJoystickTriggers,
HIDAPI_DriverSteamDeck_GetJoystickCapabilities,
HIDAPI_DriverSteamDeck_SetJoystickLED,
HIDAPI_DriverSteamDeck_SendJoystickEffect,
HIDAPI_DriverSteamDeck_SetSensorsEnabled,
HIDAPI_DriverSteamDeck_CloseJoystick,
HIDAPI_DriverSteamDeck_FreeDevice,
};
#endif /* SDL_JOYSTICK_HIDAPI_STEAMDECK */
#endif /* SDL_JOYSTICK_HIDAPI */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -63,6 +63,16 @@
#define SWITCH_ACCEL_SCALE_OFFSET 16384.0f
#define SWITCH_ACCEL_SCALE_MULT 4.0f
enum
{
SDL_GAMEPAD_BUTTON_SWITCH_SHARE = 11,
SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1,
SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1,
SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2,
SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2,
SDL_GAMEPAD_NUM_SWITCH_BUTTONS,
};
typedef enum
{
k_eSwitchInputReportIDs_SubcommandReply = 0x21,
@ -263,13 +273,14 @@ typedef struct
SDL_HIDAPI_Device *device;
SDL_Joystick *joystick;
SDL_bool m_bInputOnly;
SDL_bool m_bIsGameCube;
SDL_bool m_bUseButtonLabels;
SDL_bool m_bPlayerLights;
int m_nPlayerIndex;
SDL_bool m_bSyncWrite;
int m_nMaxWriteAttempts;
ESwitchDeviceInfoControllerType m_eControllerType;
Uint8 m_nInitialInputMode;
Uint8 m_nCurrentInputMode;
Uint8 m_rgucMACAddress[6];
Uint8 m_nCommandNumber;
SwitchCommonOutputPacket_t m_RumblePacket;
@ -438,7 +449,7 @@ static SDL_bool WriteSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommand
SwitchSubcommandInputPacket_t *reply = NULL;
int nTries;
for (nTries = 1; reply == NULL && nTries <= ctx->m_nMaxWriteAttempts; ++nTries) {
for (nTries = 1; !reply && nTries <= ctx->m_nMaxWriteAttempts; ++nTries) {
SwitchSubcommandOutputPacket_t commandPacket;
ConstructSubcommand(ctx, ucCommandID, pBuf, ucLen, &commandPacket);
@ -462,7 +473,7 @@ static SDL_bool WriteProprietary(SDL_DriverSwitch_Context *ctx, ESwitchProprieta
for (nTries = 1; nTries <= ctx->m_nMaxWriteAttempts; ++nTries) {
SwitchProprietaryOutputPacket_t packet;
if ((pBuf == NULL && ucLen > 0) || ucLen > sizeof(packet.rgucProprietaryData)) {
if ((!pBuf && ucLen > 0) || ucLen > sizeof(packet.rgucProprietaryData)) {
return SDL_FALSE;
}
@ -644,7 +655,13 @@ static SDL_bool SetVibrationEnabled(SDL_DriverSwitch_Context *ctx, Uint8 enabled
}
static SDL_bool SetInputMode(SDL_DriverSwitch_Context *ctx, Uint8 input_mode)
{
return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetInputReportMode, &input_mode, sizeof(input_mode), NULL);
if (input_mode == ctx->m_nCurrentInputMode) {
return SDL_TRUE;
} else {
ctx->m_nCurrentInputMode = input_mode;
return WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SetInputReportMode, &input_mode, sizeof(input_mode), NULL);
}
}
static SDL_bool SetHomeLED(SDL_DriverSwitch_Context *ctx, Uint8 brightness)
@ -713,15 +730,29 @@ static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, c
}
}
static Uint8 GetInitialInputMode(SDL_DriverSwitch_Context *ctx)
{
Uint8 input_mode = 0;
if (ReadInput(ctx) > 0) {
input_mode = ctx->m_rgucReadBuffer[0];
}
return input_mode;
}
static Uint8 GetDefaultInputMode(SDL_DriverSwitch_Context *ctx)
{
Uint8 input_mode;
/* Determine the desired input mode */
if (ctx->device->is_bluetooth) {
input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
if (ctx->m_nInitialInputMode) {
input_mode = ctx->m_nInitialInputMode;
} else {
input_mode = k_eSwitchInputReportIDs_FullControllerState;
if (ctx->device->is_bluetooth) {
input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
} else {
input_mode = k_eSwitchInputReportIDs_FullControllerState;
}
}
/* The official Nintendo Switch Pro Controller supports FullControllerState over Bluetooth
@ -735,6 +766,20 @@ static Uint8 GetDefaultInputMode(SDL_DriverSwitch_Context *ctx)
return input_mode;
}
static Uint8 GetSensorInputMode(SDL_DriverSwitch_Context *ctx)
{
Uint8 input_mode;
/* Determine the desired input mode */
if (!ctx->m_nInitialInputMode ||
ctx->m_nInitialInputMode == k_eSwitchInputReportIDs_SimpleControllerState) {
input_mode = k_eSwitchInputReportIDs_FullControllerState;
} else {
input_mode = ctx->m_nInitialInputMode;
}
return input_mode;
}
static SDL_bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, SDL_bool enabled)
{
Uint8 imu_data = enabled ? 1 : 0;
@ -909,8 +954,7 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax,
SDL_MIN_SINT16, SDL_MAX_SINT16);
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
@ -927,42 +971,24 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax,
SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata;
ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
{
if (!ctx->m_bUseButtonLabels) {
/* Use button positions */
if (ctx->m_bIsGameCube) {
switch (button) {
case SDL_GAMEPAD_BUTTON_B:
return SDL_GAMEPAD_BUTTON_X;
case SDL_GAMEPAD_BUTTON_X:
return SDL_GAMEPAD_BUTTON_B;
default:
break;
}
} else {
switch (button) {
case SDL_GAMEPAD_BUTTON_A:
return SDL_GAMEPAD_BUTTON_B;
case SDL_GAMEPAD_BUTTON_B:
return SDL_GAMEPAD_BUTTON_A;
case SDL_GAMEPAD_BUTTON_X:
return SDL_GAMEPAD_BUTTON_Y;
case SDL_GAMEPAD_BUTTON_Y:
return SDL_GAMEPAD_BUTTON_X;
default:
break;
}
if (ctx->m_bUseButtonLabels) {
/* Use button labels instead of positions, e.g. Nintendo Online Classic controllers */
switch (button) {
case SDL_GAMEPAD_BUTTON_SOUTH:
return SDL_GAMEPAD_BUTTON_EAST;
case SDL_GAMEPAD_BUTTON_EAST:
return SDL_GAMEPAD_BUTTON_SOUTH;
case SDL_GAMEPAD_BUTTON_WEST:
return SDL_GAMEPAD_BUTTON_NORTH;
case SDL_GAMEPAD_BUTTON_NORTH:
return SDL_GAMEPAD_BUTTON_WEST;
default:
break;
}
}
return button;
@ -1049,9 +1075,12 @@ static SDL_bool HasHomeLED(SDL_DriverSwitch_Context *ctx)
return SDL_TRUE;
}
static SDL_bool AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInfoControllerType eControllerType)
static SDL_bool AlwaysUsesLabels(Uint16 vendor_id, Uint16 product_id, ESwitchDeviceInfoControllerType eControllerType)
{
/* These controllers don't have a diamond button configuration, so always use labels */
/* Some controllers don't have a diamond button configuration, so should always use labels */
if (SDL_IsJoystickGameCube(vendor_id, product_id)) {
return SDL_TRUE;
}
switch (eControllerType) {
case k_eSwitchDeviceInfoControllerType_HVCLeft:
case k_eSwitchDeviceInfoControllerType_HVCRight:
@ -1065,23 +1094,6 @@ static SDL_bool AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInf
}
}
static SDL_bool IsGameCubeFormFactor(int vendor_id, int product_id)
{
static Uint32 gamecube_formfactor[] = {
MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */
MAKE_VIDPID(0x20d6, 0xa711), /* Core (Plus) Wired Controller */
};
Uint32 id = MAKE_VIDPID(vendor_id, product_id);
int i;
for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) {
if (id == gamecube_formfactor[i]) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static void HIDAPI_DriverNintendoClassic_RegisterHints(SDL_HintCallback callback, void *userdata)
{
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata);
@ -1192,79 +1204,86 @@ static SDL_bool HIDAPI_DriverSwitch_IsSupportedDevice(SDL_HIDAPI_Device *device,
return SDL_FALSE;
}
return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE;
return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO);
}
static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
{
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
char serial[18];
switch (ctx->m_eControllerType) {
case k_eSwitchDeviceInfoControllerType_JoyConLeft:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT);
device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
break;
case k_eSwitchDeviceInfoControllerType_JoyConRight:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT);
device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
break;
case k_eSwitchDeviceInfoControllerType_ProController:
case k_eSwitchDeviceInfoControllerType_LicProController:
HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_PRO);
device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
break;
case k_eSwitchDeviceInfoControllerType_HVCLeft:
HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (1)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_HVCRight:
HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (2)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_NESLeft:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_NESRight:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_SNES:
HIDAPI_SetDeviceName(device, "Nintendo SNES Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SNES_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_N64:
HIDAPI_SetDeviceName(device, "Nintendo N64 Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_N64_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_Unknown:
/* We couldn't read the device info for this controller, might not be fully compliant */
return;
default:
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
if (ctx->m_bInputOnly) {
if (SDL_IsJoystickGameCube(device->vendor_id, device->product_id)) {
device->type = SDL_GAMEPAD_TYPE_STANDARD;
}
} else {
char serial[18];
switch (ctx->m_eControllerType) {
case k_eSwitchDeviceInfoControllerType_JoyConLeft:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT);
device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
break;
case k_eSwitchDeviceInfoControllerType_JoyConRight:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT);
device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
break;
case k_eSwitchDeviceInfoControllerType_ProController:
case k_eSwitchDeviceInfoControllerType_LicProController:
HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SWITCH_PRO);
device->type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
break;
case k_eSwitchDeviceInfoControllerType_HVCLeft:
HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (1)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_HVCRight:
HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (2)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_NESLeft:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_NESRight:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)");
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_SNES:
HIDAPI_SetDeviceName(device, "Nintendo SNES Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SNES_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_N64:
HIDAPI_SetDeviceName(device, "Nintendo N64 Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_N64_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_Unknown:
/* We couldn't read the device info for this controller, might not be fully compliant */
return;
default:
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
}
device->guid.data[15] = ctx->m_eControllerType;
(void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
ctx->m_rgucMACAddress[0],
ctx->m_rgucMACAddress[1],
ctx->m_rgucMACAddress[2],
ctx->m_rgucMACAddress[3],
ctx->m_rgucMACAddress[4],
ctx->m_rgucMACAddress[5]);
HIDAPI_SetDeviceSerial(device, serial);
}
device->guid.data[15] = ctx->m_eControllerType;
(void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
ctx->m_rgucMACAddress[0],
ctx->m_rgucMACAddress[1],
ctx->m_rgucMACAddress[2],
ctx->m_rgucMACAddress[3],
ctx->m_rgucMACAddress[4],
ctx->m_rgucMACAddress[5]);
HIDAPI_SetDeviceSerial(device, serial);
}
static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
@ -1272,8 +1291,7 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverSwitch_Context *ctx;
ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -1282,11 +1300,6 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
ctx->m_nMaxWriteAttempts = GetMaxWriteAttempts(device);
ctx->m_bSyncWrite = SDL_TRUE;
if (IsGameCubeFormFactor(device->vendor_id, device->product_id)) {
/* This is a controller shaped like a GameCube controller, with a large central A button */
ctx->m_bIsGameCube = SDL_TRUE;
}
/* Find out whether or not we can send output reports */
ctx->m_bInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(device->vendor_id, device->product_id);
if (!ctx->m_bInputOnly) {
@ -1295,8 +1308,8 @@ static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device)
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
BReadDeviceInfo(ctx);
UpdateDeviceIdentity(device);
}
UpdateDeviceIdentity(device);
/* Prefer the USB device over the Bluetooth device */
if (device->is_bluetooth) {
@ -1338,6 +1351,9 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
ctx->m_bSyncWrite = SDL_TRUE;
if (!ctx->m_bInputOnly) {
ctx->m_nInitialInputMode = GetInitialInputMode(ctx);
ctx->m_nCurrentInputMode = ctx->m_nInitialInputMode;
/* Initialize rumble data */
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
@ -1416,9 +1432,6 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
if (AlwaysUsesLabels(device->vendor_id, device->product_id, ctx->m_eControllerType)) {
ctx->m_bUseButtonLabels = SDL_TRUE;
} else {
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
}
/* Initialize player index (needed for setting LEDs) */
@ -1430,8 +1443,9 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_
SDL_PlayerLEDHintChanged, ctx);
/* Initialize the joystick capabilities */
joystick->nbuttons = 20;
joystick->nbuttons = SDL_GAMEPAD_NUM_SWITCH_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
joystick->epowerlevel = device->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
/* Set up for input */
@ -1466,7 +1480,7 @@ static int HIDAPI_DriverSwitch_ActuallyRumbleJoystick(SDL_DriverSwitch_Context *
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
}
ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE;
ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble);
if (!WriteRumble(ctx)) {
return SDL_SetError("Couldn't send rumble packet");
@ -1626,7 +1640,7 @@ static int HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *devi
Uint8 input_mode;
if (enabled) {
input_mode = k_eSwitchInputReportIDs_FullControllerState;
input_mode = GetSensorInputMode(ctx);
} else {
input_mode = GetDefaultInputMode(ctx);
}
@ -1647,10 +1661,10 @@ static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwi
if (packet->rgucButtons[0] != ctx->m_lastInputOnlyState.rgucButtons[0]) {
Uint8 data = packet->rgucButtons[0];
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
@ -1668,51 +1682,42 @@ static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwi
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}
if (packet->ucStickHat != ctx->m_lastInputOnlyState.ucStickHat) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (packet->ucStickHat) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
if (packet->rgucJoystickLeft[0] != ctx->m_lastInputOnlyState.rgucJoystickLeft[0]) {
@ -1745,10 +1750,10 @@ static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch
if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
Uint8 data = packet->rgucButtons[0];
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
@ -1766,51 +1771,42 @@ static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}
if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (packet->ucStickHat) {
case 0:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 1:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 2:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 3:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 5:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 7:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
axis = ApplySimpleStickCalibration(ctx, 0, 0, packet->sJoystickLeft[0]);
@ -1879,17 +1875,29 @@ static void HandleCombinedControllerStateL(Uint64 timestamp, SDL_Joystick *joyst
Uint8 data = packet->controllerState.rgucButtons[1];
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}
if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
Uint8 data = packet->controllerState.rgucButtons[2];
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
Uint8 hat = 0;
if (data & 0x01) {
hat |= SDL_HAT_DOWN;
}
if (data & 0x02) {
hat |= SDL_HAT_UP;
}
if (data & 0x04) {
hat |= SDL_HAT_RIGHT;
}
if (data & 0x08) {
hat |= SDL_HAT_LEFT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
@ -1917,14 +1925,14 @@ static void HandleMiniControllerStateL(Uint64 timestamp, SDL_Joystick *joystick,
if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
Uint8 data = packet->controllerState.rgucButtons[2];
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_LEFT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
@ -1942,12 +1950,12 @@ static void HandleCombinedControllerStateR(Uint64 timestamp, SDL_Joystick *joyst
if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
Uint8 data = packet->controllerState.rgucButtons[0];
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
@ -1975,14 +1983,14 @@ static void HandleMiniControllerStateR(Uint64 timestamp, SDL_Joystick *joystick,
if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
Uint8 data = packet->controllerState.rgucButtons[0];
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE1, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_RIGHT_PADDLE2, (data & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
@ -2022,10 +2030,10 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
Uint8 data = packet->controllerState.rgucButtons[0];
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_A), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_SOUTH), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_EAST), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_WEST), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, RemapButton(ctx, SDL_GAMEPAD_BUTTON_NORTH), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
@ -2039,15 +2047,27 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SWITCH_SHARE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}
if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
Uint8 data = packet->controllerState.rgucButtons[2];
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
Uint8 hat = 0;
if (data & 0x01) {
hat |= SDL_HAT_DOWN;
}
if (data & 0x02) {
hat |= SDL_HAT_UP;
}
if (data & 0x04) {
hat |= SDL_HAT_RIGHT;
}
if (data & 0x08) {
hat |= SDL_HAT_LEFT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
axis = (data & 0x80) ? 32767 : -32768;
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
@ -2070,24 +2090,26 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, ~axis);
}
/* High nibble of battery/connection byte is battery level, low nibble is connection status
* LSB of connection nibble is USB/Switch connection status
*/
if (packet->controllerState.ucBatteryAndConnection & 0x1) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
} else {
/* LSB of the battery nibble is used to report charging.
* The battery level is reported from 0(empty)-8(full)
if (ctx->device->is_bluetooth) {
/* High nibble of battery/connection byte is battery level, low nibble is connection status
* LSB of connection nibble is USB/Switch connection status
*/
int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4;
if (level == 0) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
} else if (level <= 2) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
} else if (level <= 6) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
if (packet->controllerState.ucBatteryAndConnection & 0x1) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
} else {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
/* LSB of the battery nibble is used to report charging.
* The battery level is reported from 0(empty)-8(full)
*/
int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4;
if (level == 0) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
} else if (level <= 2) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
} else if (level <= 6) {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
} else {
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
}
}
}
@ -2203,13 +2225,15 @@ static SDL_bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
++packet_count;
ctx->m_ulLastInput = now;
if (joystick == NULL) {
if (!joystick) {
continue;
}
if (ctx->m_bInputOnly) {
HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]);
} else {
ctx->m_nCurrentInputMode = ctx->m_rgucReadBuffer[0];
switch (ctx->m_rgucReadBuffer[0]) {
case k_eSwitchInputReportIDs_SimpleControllerState:
HandleSimpleControllerState(joystick, ctx, (SwitchSimpleStatePacket_t *)&ctx->m_rgucReadBuffer[1]);
@ -2276,12 +2300,12 @@ static void HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joy
if (!ctx->m_bInputOnly) {
/* Restore simple input mode for other applications */
SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
if (!ctx->m_nInitialInputMode ||
ctx->m_nInitialInputMode == k_eSwitchInputReportIDs_SimpleControllerState) {
SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
}
}
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -135,7 +135,6 @@ typedef struct
Uint64 timestamp;
EWiiCommunicationState m_eCommState;
EWiiExtensionControllerType m_eExtensionControllerType;
SDL_bool m_bUseButtonLabels;
SDL_bool m_bPlayerLights;
int m_nPlayerIndex;
SDL_bool m_bRumbleActive;
@ -231,7 +230,7 @@ static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs exp
int nRead = 0;
while ((nRead = ReadInput(ctx)) != -1) {
if (nRead > 0) {
if (ctx->m_rgucReadBuffer[0] == expectedID && (isMine == NULL || isMine(ctx->m_rgucReadBuffer))) {
if (ctx->m_rgucReadBuffer[0] == expectedID && (!isMine || isMine(ctx->m_rgucReadBuffer))) {
return SDL_TRUE;
}
} else {
@ -273,7 +272,7 @@ static SDL_bool WriteRegister(SDL_DriverWii_Context *ctx, Uint32 address, const
return SDL_FALSE;
}
if (ctx->m_rgucReadBuffer[4]) {
SDL_SetError("Write memory failed: %d", ctx->m_rgucReadBuffer[4]);
SDL_SetError("Write memory failed: %u", ctx->m_rgucReadBuffer[4]);
return SDL_FALSE;
}
}
@ -336,7 +335,7 @@ static SDL_bool ParseExtensionIdentifyResponse(SDL_DriverWii_Context *ctx, Uint1
}
if (error) {
SDL_SetError("Failed to read extension type: %d", error);
SDL_SetError("Failed to read extension type: %u", error);
} else {
SDL_SetError("Unexpected read length when reading extension type: %d", (ctx->m_rgucReadBuffer[3] >> 4) + 1);
}
@ -505,8 +504,8 @@ static void UpdatePowerLevelWii(SDL_Joystick *joystick, Uint8 batteryLevelByte)
static void UpdatePowerLevelWiiU(SDL_Joystick *joystick, Uint8 extensionBatteryByte)
{
SDL_bool charging = extensionBatteryByte & 0x08 ? SDL_FALSE : SDL_TRUE;
SDL_bool pluggedIn = extensionBatteryByte & 0x04 ? SDL_FALSE : SDL_TRUE;
SDL_bool charging = !(extensionBatteryByte & 0x08);
SDL_bool pluggedIn = !(extensionBatteryByte & 0x04);
Uint8 batteryLevel = extensionBatteryByte >> 4;
/* Not sure if all Wii U Pro controllers act like this, but on mine
@ -552,7 +551,7 @@ static EWiiInputReportIDs GetButtonPacketType(SDL_DriverWii_Context *ctx)
static SDL_bool RequestButtonPacketType(SDL_DriverWii_Context *ctx, EWiiInputReportIDs type)
{
Uint8 data[3];
Uint8 tt = ctx->m_bRumbleActive;
Uint8 tt = (Uint8)ctx->m_bRumbleActive;
/* Continuous reporting off, tt & 4 == 0 */
if (ENABLE_CONTINUOUS_REPORTING) {
@ -610,19 +609,13 @@ static void InitializeExtension(SDL_DriverWii_Context *ctx)
ResetButtonPacketType(ctx);
}
static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)userdata;
ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
}
static void UpdateSlotLED(SDL_DriverWii_Context *ctx)
{
Uint8 leds;
Uint8 data[2];
/* The lowest bit needs to have the rumble status */
leds = ctx->m_bRumbleActive;
leds = (Uint8)ctx->m_bRumbleActive;
if (ctx->m_bPlayerLights) {
/* Use the same LED codes as Smash 8-player for 5-7 */
@ -725,8 +718,7 @@ static SDL_bool HIDAPI_DriverWii_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverWii_Context *ctx;
ctx = (SDL_DriverWii_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -786,9 +778,6 @@ static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
}
}
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
/* Initialize player index (needed for setting LEDs) */
ctx->m_nPlayerIndex = SDL_GetJoystickPlayerIndex(joystick);
ctx->m_bPlayerLights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED, SDL_TRUE);
@ -814,13 +803,13 @@ static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
static int HIDAPI_DriverWii_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
SDL_bool active = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE;
SDL_bool active = (low_frequency_rumble || high_frequency_rumble);
if (active != ctx->m_bRumbleActive) {
Uint8 data[2];
data[0] = k_eWiiOutputReportIDs_Rumble;
data[1] = active;
data[1] = (Uint8)active;
WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
ctx->m_bRumbleActive = active;
@ -940,43 +929,10 @@ static const Uint8 GAMEPAD_BUTTON_DEFS[3][8] = {
SDL_GAMEPAD_BUTTON_DPAD_UP,
SDL_GAMEPAD_BUTTON_DPAD_LEFT,
0xFF /* ZR */,
SDL_GAMEPAD_BUTTON_X,
SDL_GAMEPAD_BUTTON_A,
SDL_GAMEPAD_BUTTON_Y,
SDL_GAMEPAD_BUTTON_B,
0xFF /*ZL*/,
},
{
SDL_GAMEPAD_BUTTON_RIGHT_STICK,
SDL_GAMEPAD_BUTTON_LEFT_STICK,
0xFF /* Charging */,
0xFF /* Plugged In */,
0xFF /* Unused */,
0xFF /* Unused */,
0xFF /* Unused */,
0xFF /* Unused */,
}
};
static const Uint8 GAMEPAD_BUTTON_DEFS_POSITIONAL[3][8] = {
{
0xFF /* Unused */,
SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER,
SDL_GAMEPAD_BUTTON_START,
SDL_GAMEPAD_BUTTON_GUIDE,
SDL_GAMEPAD_BUTTON_BACK,
SDL_GAMEPAD_BUTTON_LEFT_SHOULDER,
SDL_GAMEPAD_BUTTON_DPAD_DOWN,
SDL_GAMEPAD_BUTTON_DPAD_RIGHT,
},
{
SDL_GAMEPAD_BUTTON_DPAD_UP,
SDL_GAMEPAD_BUTTON_DPAD_LEFT,
0xFF /* ZR */,
SDL_GAMEPAD_BUTTON_Y,
SDL_GAMEPAD_BUTTON_B,
SDL_GAMEPAD_BUTTON_X,
SDL_GAMEPAD_BUTTON_A,
SDL_GAMEPAD_BUTTON_NORTH,
SDL_GAMEPAD_BUTTON_EAST,
SDL_GAMEPAD_BUTTON_WEST,
SDL_GAMEPAD_BUTTON_SOUTH,
0xFF /*ZL*/,
},
{
@ -1006,43 +962,10 @@ static const Uint8 MP_GAMEPAD_BUTTON_DEFS[3][8] = {
0xFF /* Motion Plus data */,
0xFF /* Motion Plus data */,
0xFF /* ZR */,
SDL_GAMEPAD_BUTTON_X,
SDL_GAMEPAD_BUTTON_A,
SDL_GAMEPAD_BUTTON_Y,
SDL_GAMEPAD_BUTTON_B,
0xFF /*ZL*/,
},
{
SDL_GAMEPAD_BUTTON_RIGHT_STICK,
SDL_GAMEPAD_BUTTON_LEFT_STICK,
0xFF /* Charging */,
0xFF /* Plugged In */,
0xFF /* Unused */,
0xFF /* Unused */,
0xFF /* Unused */,
0xFF /* Unused */,
}
};
static const Uint8 MP_GAMEPAD_BUTTON_DEFS_POSITIONAL[3][8] = {
{
0xFF /* Unused */,
SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER,
SDL_GAMEPAD_BUTTON_START,
SDL_GAMEPAD_BUTTON_GUIDE,
SDL_GAMEPAD_BUTTON_BACK,
SDL_GAMEPAD_BUTTON_LEFT_SHOULDER,
SDL_GAMEPAD_BUTTON_DPAD_DOWN,
SDL_GAMEPAD_BUTTON_DPAD_RIGHT,
},
{
0xFF /* Motion Plus data */,
0xFF /* Motion Plus data */,
0xFF /* ZR */,
SDL_GAMEPAD_BUTTON_Y,
SDL_GAMEPAD_BUTTON_B,
SDL_GAMEPAD_BUTTON_X,
SDL_GAMEPAD_BUTTON_A,
SDL_GAMEPAD_BUTTON_NORTH,
SDL_GAMEPAD_BUTTON_EAST,
SDL_GAMEPAD_BUTTON_WEST,
SDL_GAMEPAD_BUTTON_SOUTH,
0xFF /*ZL*/,
},
{
@ -1083,7 +1006,7 @@ static const Uint8 MP_FIXUP_DPAD_BUTTON_DEFS[2][8] = {
static void HandleWiiUProButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
{
static const Uint8 axes[] = { SDL_GAMEPAD_AXIS_LEFTX, SDL_GAMEPAD_AXIS_RIGHTX, SDL_GAMEPAD_AXIS_LEFTY, SDL_GAMEPAD_AXIS_RIGHTY };
const Uint8(*buttons)[8] = ctx->m_bUseButtonLabels ? GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS_POSITIONAL;
const Uint8(*buttons)[8] = GAMEPAD_BUTTON_DEFS;
Uint8 zl, zr;
int i;
@ -1112,7 +1035,7 @@ static void HandleWiiUProButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *jo
static void HandleGamepadControllerButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
{
const Uint8(*buttons)[8] = ctx->m_bUseButtonLabels ? ((ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS) : ((ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS_POSITIONAL : GAMEPAD_BUTTON_DEFS_POSITIONAL);
const Uint8(*buttons)[8] = (ctx->m_ucMotionPlusMode == WII_MOTIONPLUS_MODE_GAMEPAD) ? MP_GAMEPAD_BUTTON_DEFS : GAMEPAD_BUTTON_DEFS;
Uint8 lx, ly, rx, ry, zl, zr;
if (data->ucNExtensionBytes < 6) {
@ -1194,10 +1117,10 @@ static void HandleWiiRemoteButtonDataAsMainController(SDL_DriverWii_Context *ctx
0xFF /* Unused */,
},
{
SDL_GAMEPAD_BUTTON_Y,
SDL_GAMEPAD_BUTTON_X,
SDL_GAMEPAD_BUTTON_A,
SDL_GAMEPAD_BUTTON_B,
SDL_GAMEPAD_BUTTON_NORTH,
SDL_GAMEPAD_BUTTON_WEST,
SDL_GAMEPAD_BUTTON_SOUTH,
SDL_GAMEPAD_BUTTON_EAST,
SDL_GAMEPAD_BUTTON_BACK,
0xFF /* Unused */,
0xFF /* Unused */,
@ -1407,7 +1330,7 @@ static void GetExtensionData(WiiButtonData *dst, const Uint8 *src, int size)
static void HandleStatus(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick)
{
SDL_bool hadExtension = ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_None;
SDL_bool hasExtension = ctx->m_rgucReadBuffer[3] & 2 ? SDL_TRUE : SDL_FALSE;
SDL_bool hasExtension = (ctx->m_rgucReadBuffer[3] & 2) ? SDL_TRUE : SDL_FALSE;
WiiButtonData data;
SDL_zero(data);
GetBaseButtons(&data, ctx->m_rgucReadBuffer + 1);
@ -1618,7 +1541,7 @@ static SDL_bool HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device)
Uint8 data[2];
data[0] = k_eWiiOutputReportIDs_StatusRequest;
data[1] = ctx->m_bRumbleActive;
data[1] = (Uint8)ctx->m_bRumbleActive;
WriteOutput(ctx, data, sizeof(data), SDL_FALSE);
ctx->m_ulLastStatus = now;
@ -1637,9 +1560,6 @@ static void HIDAPI_DriverWii_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joysti
{
SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context;
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED,
SDL_PlayerLEDHintChanged, ctx);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -71,7 +71,7 @@ static SDL_bool HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device
/* This is the NVIDIA Shield controller which doesn't talk Xbox controller protocol */
return SDL_FALSE;
}
if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == 0x0291 || product_id == 0x0719)) ||
if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY2 || product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER)) ||
(type == SDL_GAMEPAD_TYPE_XBOX360 && interface_protocol == XB360W_IFACE_PROTOCOL)) {
/* This is the wireless dongle, which talks a different protocol */
return SDL_FALSE;
@ -94,9 +94,9 @@ static SDL_bool HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device
if (SDL_IsJoystickBluetoothXboxOne(vendor_id, product_id)) {
return SDL_FALSE;
}
return (type == SDL_GAMEPAD_TYPE_XBOX360 || type == SDL_GAMEPAD_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE;
return (type == SDL_GAMEPAD_TYPE_XBOX360 || type == SDL_GAMEPAD_TYPE_XBOXONE);
#else
return (type == SDL_GAMEPAD_TYPE_XBOX360) ? SDL_TRUE : SDL_FALSE;
return (type == SDL_GAMEPAD_TYPE_XBOX360);
#endif
}
@ -139,8 +139,7 @@ static SDL_bool HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverXbox360_Context *ctx;
ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -188,8 +187,9 @@ static SDL_bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL
SDL_PlayerLEDHintChanged, ctx);
/* Initialize the joystick capabilities */
joystick->nbuttons = 15;
joystick->nbuttons = 11;
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
return SDL_TRUE;
@ -270,10 +270,22 @@ static void HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, SDL_D
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[2] != data[2]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
Uint8 hat = 0;
if (data[2] & 0x01) {
hat |= SDL_HAT_UP;
}
if (data[2] & 0x02) {
hat |= SDL_HAT_DOWN;
}
if (data[2] & 0x04) {
hat |= SDL_HAT_LEFT;
}
if (data[2] & 0x08) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
@ -284,10 +296,10 @@ static void HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, SDL_D
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
axis = ((int)data[4] * 257) - 32768;
@ -329,7 +341,7 @@ static SDL_bool HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox 360 packet: size = %d", data, size);
#endif
if (joystick == NULL) {
if (!joystick) {
continue;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -65,7 +65,7 @@ static SDL_bool HIDAPI_DriverXbox360W_IsSupportedDevice(SDL_HIDAPI_Device *devic
{
const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == 0x0291 || product_id == 0x02a9 || product_id == 0x0719) && interface_protocol == 0) ||
if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY2 || product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY1 || product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER) && interface_protocol == 0) ||
(type == SDL_GAMEPAD_TYPE_XBOX360 && interface_protocol == XB360W_IFACE_PROTOCOL)) {
return SDL_TRUE;
}
@ -131,8 +131,7 @@ static SDL_bool HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
HIDAPI_SetDeviceName(device, "Xbox 360 Wireless Controller");
ctx = (SDL_DriverXbox360W_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -158,7 +157,7 @@ static void HIDAPI_DriverXbox360W_SetDevicePlayerIndex(SDL_HIDAPI_Device *device
{
SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context;
if (ctx == NULL) {
if (!ctx) {
return;
}
@ -237,10 +236,22 @@ static void HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, SDL_
Uint64 timestamp = SDL_GetTicksNS();
if (ctx->last_state[2] != data[2]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
Uint8 hat = 0;
if (data[2] & 0x01) {
hat |= SDL_HAT_UP;
}
if (data[2] & 0x02) {
hat |= SDL_HAT_DOWN;
}
if (data[2] & 0x04) {
hat |= SDL_HAT_LEFT;
}
if (data[2] & 0x08) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
@ -251,10 +262,10 @@ static void HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, SDL_
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
axis = ((int)data[4] * 257) - 32768;

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -49,6 +49,11 @@
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD -25058 /* Uint8 30 scaled to Sint16 full range */
enum
{
SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON = 11
};
/* Power on */
static const Uint8 xbox_init_power_on[] = {
0x05, 0x20, 0x00, 0x01, 0x00
@ -351,7 +356,7 @@ static SDL_bool HIDAPI_DriverXboxOne_IsSupportedDevice(SDL_HIDAPI_Device *device
return SDL_FALSE;
}
#endif
return (type == SDL_GAMEPAD_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE;
return (type == SDL_GAMEPAD_TYPE_XBOXONE);
}
static SDL_bool HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
@ -359,8 +364,7 @@ static SDL_bool HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
SDL_DriverXboxOne_Context *ctx;
ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SDL_OutOfMemory();
if (!ctx) {
return SDL_FALSE;
}
ctx->device = device;
@ -418,7 +422,7 @@ static SDL_bool HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL
SDL_zeroa(ctx->last_state);
/* Initialize the joystick capabilities */
joystick->nbuttons = 15;
joystick->nbuttons = 11;
if (ctx->has_share_button) {
joystick->nbuttons += 1;
}
@ -426,6 +430,7 @@ static SDL_bool HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL
joystick->nbuttons += 4;
}
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
joystick->nhats = 1;
if (!device->is_bluetooth) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
@ -631,7 +636,7 @@ static void HIDAPI_DriverXboxOne_HandleUnmappedStatePacket(SDL_Joystick *joystic
}
if (ctx->last_paddle_state != data[paddle_index]) {
Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_MISC1 + ctx->has_share_button); /* Next available button */
Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON + ctx->has_share_button); /* Next available button */
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
@ -659,17 +664,29 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D
if (ctx->last_state[0] != data[0]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[0] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[0] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[0] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[0] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[0] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[0] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[0] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[0] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[1] != data[1]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, (data[1] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, (data[1] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, (data[1] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
Uint8 hat = 0;
if (data[2] & 0x01) {
hat |= SDL_HAT_UP;
}
if (data[2] & 0x02) {
hat |= SDL_HAT_DOWN;
}
if (data[2] & 0x04) {
hat |= SDL_HAT_LEFT;
}
if (data[2] & 0x08) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
if (ctx->vendor_id == USB_VENDOR_RAZER && ctx->product_id == USB_PRODUCT_RAZER_ATROX) {
/* The Razer Atrox has the right and left shoulder bits reversed */
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[1] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
@ -691,19 +708,19 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D
*/
if (size < 44) {
if (ctx->last_state[14] != data[14]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
} else if (size == 44) {
if (ctx->last_state[18] != data[18]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[18] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[18] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
} else if (size == 46) {
if (ctx->last_state[28] != data[28]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[28] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[28] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
} else if (size == 60) {
if (ctx->last_state[42] != data[42]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[42] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[42] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
}
}
@ -786,7 +803,7 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D
}
if (ctx->last_paddle_state != data[paddle_index]) {
Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_MISC1 + ctx->has_share_button); /* Next available button */
Uint8 nButton = (Uint8)(SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON + ctx->has_share_button); /* Next available button */
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
@ -848,10 +865,10 @@ static void HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, SDL_Dr
static void HIDAPI_DriverXboxOneBluetooth_HandleButtons16(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, const Uint8 *data, int size)
{
if (ctx->last_state[14] != data[14]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[14] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[14] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[14] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
@ -875,10 +892,10 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleButtons16(Uint64 timestamp, SDL_
static void HIDAPI_DriverXboxOneBluetooth_HandleButtons(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{
if (ctx->last_state[14] != data[14]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
@ -894,7 +911,7 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleButtons(Uint64 timestamp, SDL_Jo
if (ctx->has_share_button) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[15] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
} else {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[15] & 0x04) || (data[16] & 0x01)) ? SDL_PRESSED : SDL_RELEASED);
}
@ -953,7 +970,7 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleButtons(Uint64 timestamp, SDL_Jo
}
if (ctx->last_paddle_state != data[paddle_index]) {
Uint8 nButton = SDL_GAMEPAD_BUTTON_MISC1; /* Next available button */
Uint8 nButton = SDL_GAMEPAD_BUTTON_XBOX_SHARE_BUTTON; /* Next available button */
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_SendJoystickButton(timestamp, joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
@ -981,47 +998,38 @@ static void HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joysti
}
if (ctx->last_state[13] != data[13]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
Uint8 hat;
switch (data[13]) {
case 1:
dpad_up = SDL_TRUE;
hat = SDL_HAT_UP;
break;
case 2:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHTUP;
break;
case 3:
dpad_right = SDL_TRUE;
hat = SDL_HAT_RIGHT;
break;
case 4:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_RIGHTDOWN;
break;
case 5:
dpad_down = SDL_TRUE;
hat = SDL_HAT_DOWN;
break;
case 6:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
hat = SDL_HAT_LEFTDOWN;
break;
case 7:
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFT;
break;
case 8:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_DOWN, dpad_down);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_UP, dpad_up);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, dpad_right);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_DPAD_LEFT, dpad_left);
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
}
axis = ((int)SDL_SwapLE16(*(Sint16 *)(&data[9])) * 64) - 32768;
@ -1146,6 +1154,10 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateInitState(SDL_DriverXboxOne_Context *
return SDL_TRUE;
}
/* GIP protocol handling adapted under the Zlib license with permission from @medusalix:
* https://github.com/medusalix/xone/blob/master/bus/protocol.h
* https://github.com/medusalix/xone/blob/master/bus/protocol.c
*/
#define GIP_HEADER_MIN_LENGTH 3
/* Internal commands */
@ -1401,7 +1413,7 @@ static SDL_bool HIDAPI_GIP_DispatchPacket(SDL_Joystick *joystick, SDL_DriverXbox
/* Ignore this packet */
break;
case GIP_CMD_VIRTUAL_KEY:
if (joystick == NULL) {
if (!joystick) {
break;
}
HIDAPI_DriverXboxOne_HandleModePacket(joystick, ctx, data, size);
@ -1436,13 +1448,13 @@ static SDL_bool HIDAPI_GIP_DispatchPacket(SDL_Joystick *joystick, SDL_DriverXbox
#endif
break;
}
if (joystick == NULL) {
if (!joystick) {
break;
}
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, ctx, data, size);
break;
case GIP_CMD_UNMAPPED_STATE:
if (joystick == NULL) {
if (!joystick) {
break;
}
HIDAPI_DriverXboxOne_HandleUnmappedStatePacket(joystick, ctx, data, size);
@ -1568,7 +1580,7 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
if (device->is_bluetooth) {
switch (data[0]) {
case 0x01:
if (joystick == NULL) {
if (!joystick) {
break;
}
if (size >= 16) {
@ -1580,13 +1592,13 @@ static SDL_bool HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
}
break;
case 0x02:
if (joystick == NULL) {
if (!joystick) {
break;
}
HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, ctx, data, size);
break;
case 0x04:
if (joystick == NULL) {
if (!joystick) {
break;
}
HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(joystick, ctx, data, size);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -66,6 +66,9 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
#ifdef SDL_JOYSTICK_HIDAPI_STEAM
&SDL_HIDAPI_DriverSteam,
#endif
#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK
&SDL_HIDAPI_DriverSteamDeck,
#endif
#ifdef SDL_JOYSTICK_HIDAPI_SWITCH
&SDL_HIDAPI_DriverNintendoClassic,
&SDL_HIDAPI_DriverJoyCons,
@ -99,7 +102,7 @@ static char *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 == NULL) {
if (!string) {
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));
@ -149,14 +152,20 @@ SDL_bool HIDAPI_SupportsPlaystationDetection(Uint16 vendor, Uint16 product)
case USB_VENDOR_HORI:
return SDL_TRUE;
case USB_VENDOR_LOGITECH:
/* Most Logitech devices are fine with this, but the F310 will lock up */
/* Most Logitech devices are fine with this, but there are a few exceptions */
if (product == USB_PRODUCT_LOGITECH_F310) {
/* The Logitech F310 gamepad will lock up */
return SDL_FALSE;
}
if (product == 0xc33f) {
/* The Logitech G815 keyboard will reset the LEDs */
return SDL_FALSE;
}
return SDL_TRUE;
case USB_VENDOR_MADCATZ:
return SDL_TRUE;
case USB_VENDOR_NACON:
case USB_VENDOR_NACON_ALT:
return SDL_TRUE;
case USB_VENDOR_PDP:
return SDL_TRUE;
@ -260,6 +269,7 @@ static SDL_GamepadType SDL_GetJoystickGameControllerProtocol(const char *name, U
interface_protocol == XBONE_IFACE_PROTOCOL) {
static const int SUPPORTED_VENDORS[] = {
0x03f0, /* HP */
0x044f, /* Thrustmaster */
0x045e, /* Microsoft */
0x0738, /* Mad Catz */
@ -607,7 +617,7 @@ static int HIDAPI_JoystickInit(void)
static SDL_bool HIDAPI_AddJoystickInstanceToDevice(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
{
SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1) * sizeof(*device->joysticks));
if (joysticks == NULL) {
if (!joysticks) {
return SDL_FALSE;
}
@ -656,7 +666,7 @@ void HIDAPI_SetDeviceName(SDL_HIDAPI_Device *device, const char *name)
void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 vendor_id, Uint16 product_id)
{
/* Don't set the device product ID directly, or we'll constantly re-enumerate this device */
device->guid = SDL_CreateJoystickGUID(device->guid.data[0], vendor_id, product_id, device->version, device->name, 'h', 0);
device->guid = SDL_CreateJoystickGUID(device->guid.data[0], vendor_id, product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0);
}
static void HIDAPI_UpdateJoystickSerial(SDL_HIDAPI_Device *device)
@ -729,7 +739,7 @@ SDL_bool HIDAPI_HasConnectedUSBDevice(const char *serial)
SDL_AssertJoysticksLocked();
if (serial == NULL) {
if (!serial) {
return SDL_FALSE;
}
@ -755,7 +765,7 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial)
SDL_AssertJoysticksLocked();
if (serial == NULL) {
if (!serial) {
return;
}
@ -790,7 +800,7 @@ SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJo
}
}
joystickID = SDL_GetNextJoystickInstanceID();
joystickID = SDL_GetNextObjectID();
HIDAPI_AddJoystickInstanceToDevice(device, joystickID);
for (i = 0; i < device->num_children; ++i) {
@ -865,7 +875,7 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
}
device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device));
if (device == NULL) {
if (!device) {
return NULL;
}
device->magic = &SDL_HIDAPI_device_magic;
@ -889,18 +899,11 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
/* Need the device name before getting the driver to know whether to ignore this device */
{
char *manufacturer_string = HIDAPI_ConvertString(info->manufacturer_string);
char *product_string = HIDAPI_ConvertString(info->product_string);
char *serial_number = HIDAPI_ConvertString(info->serial_number);
device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string);
if (manufacturer_string) {
SDL_free(manufacturer_string);
}
if (product_string) {
SDL_free(product_string);
}
device->manufacturer_string = HIDAPI_ConvertString(info->manufacturer_string);
device->product_string = HIDAPI_ConvertString(info->product_string);
device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, device->manufacturer_string, device->product_string);
if (serial_number && *serial_number) {
device->serial = serial_number;
@ -909,6 +912,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
}
if (!device->name) {
SDL_free(device->manufacturer_string);
SDL_free(device->product_string);
SDL_free(device->serial);
SDL_free(device->path);
SDL_free(device);
@ -921,7 +926,7 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
} else {
bus = SDL_HARDWARE_BUS_USB;
}
device->guid = SDL_CreateJoystickGUID(bus, device->vendor_id, device->product_id, device->version, device->name, 'h', 0);
device->guid = SDL_CreateJoystickGUID(bus, device->vendor_id, device->product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0);
device->joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD;
device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
@ -949,7 +954,9 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
}
#ifdef DEBUG_HIDAPI
SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version,
device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage,
device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
#endif
return device;
@ -963,7 +970,9 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
SDL_AssertJoysticksLocked();
#ifdef DEBUG_HIDAPI
SDL_Log("Removing HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
SDL_Log("Removing HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version,
device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage,
device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
#endif
for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) {
@ -987,6 +996,8 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
device->magic = NULL;
SDL_DestroyMutex(device->dev_lock);
SDL_free(device->manufacturer_string);
SDL_free(device->product_string);
SDL_free(device->serial);
SDL_free(device->name);
SDL_free(device->path);
@ -1037,7 +1048,7 @@ static SDL_bool HIDAPI_CreateCombinedJoyCons(void)
if (joycons[0] && joycons[1]) {
SDL_hid_device_info info;
SDL_HIDAPI_Device **children = (SDL_HIDAPI_Device **)SDL_malloc(2 * sizeof(SDL_HIDAPI_Device *));
if (children == NULL) {
if (!children) {
return SDL_FALSE;
}
children[0] = joycons[0];
@ -1168,7 +1179,7 @@ static SDL_bool HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id,
}
/* If we're looking for an XInput controller, match it against any other Xbox controller */
if (product_id == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) {
if (product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER) {
if (device->type == SDL_GAMEPAD_TYPE_XBOX360 || device->type == SDL_GAMEPAD_TYPE_XBOXONE) {
return SDL_TRUE;
}
@ -1367,6 +1378,11 @@ static const char *HIDAPI_JoystickGetDevicePath(int device_index)
return path;
}
static int HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
{
SDL_HIDAPI_Device *device;
@ -1422,14 +1438,14 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index)
SDL_AssertJoysticksLocked();
if (device == NULL || !device->driver) {
if (!device || !device->driver) {
/* This should never happen - validated before being called */
return SDL_SetError("Couldn't find HIDAPI device at index %d\n", device_index);
}
hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
if (hwdata == NULL) {
return SDL_OutOfMemory();
if (!hwdata) {
return -1;
}
hwdata->device = device;
@ -1440,6 +1456,12 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index)
device->updating = SDL_FALSE;
SDL_UnlockMutex(device->dev_lock);
/* UpdateDevice() may have called HIDAPI_JoystickDisconnected() if the device went away */
if (device->num_joysticks == 0) {
SDL_free(hwdata);
return SDL_SetError("HIDAPI device disconnected while opening");
}
if (!device->driver->OpenJoystick(device, joystick)) {
/* The open failed, mark this device as disconnected and update devices */
HIDAPI_JoystickDisconnected(device, joystickID);
@ -1639,6 +1661,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = {
HIDAPI_JoystickDetect,
HIDAPI_JoystickGetDeviceName,
HIDAPI_JoystickGetDevicePath,
HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot,
HIDAPI_JoystickGetDevicePlayerIndex,
HIDAPI_JoystickSetDevicePlayerIndex,
HIDAPI_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -33,6 +33,7 @@
#define SDL_JOYSTICK_HIDAPI_PS5
#define SDL_JOYSTICK_HIDAPI_STADIA
#define SDL_JOYSTICK_HIDAPI_STEAM /* Simple support for BLE Steam Controller, hint is disabled by default */
#define SDL_JOYSTICK_HIDAPI_STEAMDECK
#define SDL_JOYSTICK_HIDAPI_SWITCH
#define SDL_JOYSTICK_HIDAPI_WII
#define SDL_JOYSTICK_HIDAPI_XBOX360
@ -52,6 +53,8 @@ typedef struct SDL_HIDAPI_Device
{
const void *magic;
char *name;
char *manufacturer_string;
char *product_string;
char *path;
Uint16 vendor_id;
Uint16 product_id;
@ -126,6 +129,7 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamDeck;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverWii;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360;

View File

@ -47,6 +47,8 @@ enum ValveControllerPID
D0G_BLE_PID = 0x1105,
D0G_BLE2_PID = 0x1106,
D0GGLE_PID = 0x1142,
JUPITER_PID = 0x1205,
};
// This enum contains all of the messages exchanged between the host and the target (only add to this enum and never change the order)
@ -68,10 +70,11 @@ enum FeatureReportMessageIDs
ID_SET_CONTROLLER_MODE = 0x8D,
ID_LOAD_DEFAULT_SETTINGS = 0x8E,
ID_TRIGGER_HAPTIC_PULSE = 0x8F,
ID_TURN_OFF_CONTROLLER = 0x9F,
ID_GET_DEVICE_INFO = 0xA1,
ID_CALIBRATE_TRACKPADS = 0xA7,
ID_RESERVED_0 = 0xA8,
ID_SET_SERIAL_NUMBER = 0xA9,
@ -99,6 +102,12 @@ enum FeatureReportMessageIDs
ID_CHECK_GYRO_FW_LOAD = 0xC2,
ID_CALIBRATE_ANALOG = 0xC3,
ID_DONGLE_GET_CONNECTED_SLOTS = 0xC4,
ID_RESET_IMU = 0xCE,
// Deck only
ID_TRIGGER_HAPTIC_CMD = 0xEA,
ID_TRIGGER_RUMBLE_CMD = 0xEB,
};
@ -215,6 +224,32 @@ typedef enum
IO_RAW_JOYSTICK_X,
IO_RAW_JOYSTICK_Y,
IO_GYRO_TILT_VEC,
IO_PRESSURE_LEFT_PAD,
IO_PRESSURE_RIGHT_PAD,
IO_PRESSURE_LEFT_BUMPER,
IO_PRESSURE_RIGHT_BUMPER,
IO_PRESSURE_LEFT_GRIP,
IO_PRESSURE_RIGHT_GRIP,
IO_ANALOG_LEFT_TRIGGER_THRESHOLD,
IO_ANALOG_RIGHT_TRIGGER_THRESHOLD,
IO_PRESSURE_RIGHT_PAD_THRESHOLD,
IO_PRESSURE_LEFT_PAD_THRESHOLD,
IO_PRESSURE_RIGHT_BUMPER_THRESHOLD,
IO_PRESSURE_LEFT_BUMPER_THRESHOLD,
IO_PRESSURE_RIGHT_GRIP_THRESHOLD,
IO_PRESSURE_LEFT_GRIP_THRESHOLD,
IO_PRESSURE_RIGHT_PAD_RAW,
IO_PRESSURE_LEFT_PAD_RAW,
IO_PRESSURE_RIGHT_BUMPER_RAW,
IO_PRESSURE_LEFT_BUMPER_RAW,
IO_PRESSURE_RIGHT_GRIP_RAW,
IO_PRESSURE_LEFT_GRIP_RAW,
IO_PRESSURE_RIGHT_GRIP2_THRESHOLD,
IO_PRESSURE_LEFT_GRIP2_THRESHOLD,
IO_PRESSURE_LEFT_GRIP2,
IO_PRESSURE_RIGHT_GRIP2,
IO_PRESSURE_RIGHT_GRIP2_RAW,
IO_PRESSURE_LEFT_GRIP2_RAW,
IO_ANALOG_COUNT
} AnalogIO;
@ -382,13 +417,15 @@ typedef enum
SETTING_MOUSE_SENSITIVITY,
SETTING_MOUSE_ACCELERATION,
SETTING_TRACKBALL_ROTATION_ANGLE,
SETTING_HAPTIC_INTENSITY,
SETTING_HAPTIC_INTENSITY_UNUSED,
SETTING_LEFT_GAMEPAD_STICK_ENABLED,
SETTING_RIGHT_GAMEPAD_STICK_ENABLED,
SETTING_USB_DEBUG_MODE,
SETTING_LEFT_TRACKPAD_MODE,
SETTING_RIGHT_TRACKPAD_MODE,
SETTING_MOUSE_POINTER_ENABLED,
// 10
SETTING_DPAD_DEADZONE,
SETTING_MINIMUM_MOMENTUM_VEL,
SETTING_MOMENTUM_DECAY_AMMOUNT,
@ -399,6 +436,8 @@ typedef enum
SETTING_MOMENTUM_VERTICAL_DIVISOR,
SETTING_MOMENTUM_MAXIMUM_VELOCITY,
SETTING_TRACKPAD_Z_ON,
// 20
SETTING_TRACKPAD_Z_OFF,
SETTING_SENSITIVY_SCALE_AMMOUNT,
SETTING_LEFT_TRACKPAD_SECONDARY_MODE,
@ -409,6 +448,8 @@ typedef enum
SETTING_TRACKPAD_OUTER_RADIUS,
SETTING_TRACKPAD_Z_ON_LEFT,
SETTING_TRACKPAD_Z_OFF_LEFT,
// 30
SETTING_TRACKPAD_OUTER_SPIN_VEL,
SETTING_TRACKPAD_OUTER_SPIN_RADIUS,
SETTING_TRACKPAD_OUTER_SPIN_HORIZONTAL_ONLY,
@ -419,6 +460,8 @@ typedef enum
SETTING_TRACKPAD_DOUBLE_TAP_BEEP_PERIOD,
SETTING_TRACKPAD_DOUBLE_TAP_BEEP_COUNT,
SETTING_TRACKPAD_OUTER_RADIUS_RELEASE_ON_TRANSITION,
// 40
SETTING_RADIAL_MODE_ANGLE,
SETTING_HAPTIC_INTENSITY_MOUSE_MODE,
SETTING_LEFT_DPAD_REQUIRES_CLICK,
@ -427,9 +470,48 @@ typedef enum
SETTING_LED_USER_BRIGHTNESS,
SETTING_ENABLE_RAW_JOYSTICK,
SETTING_ENABLE_FAST_SCAN,
SETTING_GYRO_MODE,
SETTING_IMU_MODE,
SETTING_WIRELESS_PACKET_VERSION,
// 50
SETTING_SLEEP_INACTIVITY_TIMEOUT,
SETTING_TRACKPAD_NOISE_THRESHOLD,
SETTING_LEFT_TRACKPAD_CLICK_PRESSURE,
SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE,
SETTING_LEFT_BUMPER_CLICK_PRESSURE,
SETTING_RIGHT_BUMPER_CLICK_PRESSURE,
SETTING_LEFT_GRIP_CLICK_PRESSURE,
SETTING_RIGHT_GRIP_CLICK_PRESSURE,
SETTING_LEFT_GRIP2_CLICK_PRESSURE,
SETTING_RIGHT_GRIP2_CLICK_PRESSURE,
// 60
SETTING_PRESSURE_MODE,
SETTING_CONTROLLER_TEST_MODE,
SETTING_TRIGGER_MODE,
SETTING_TRACKPAD_Z_THRESHOLD,
SETTING_FRAME_RATE,
SETTING_TRACKPAD_FILT_CTRL,
SETTING_TRACKPAD_CLIP,
SETTING_DEBUG_OUTPUT_SELECT,
SETTING_TRIGGER_THRESHOLD_PERCENT,
SETTING_TRACKPAD_FREQUENCY_HOPPING,
// 70
SETTING_HAPTICS_ENABLED,
SETTING_STEAM_WATCHDOG_ENABLE,
SETTING_TIMP_TOUCH_THRESHOLD_ON,
SETTING_TIMP_TOUCH_THRESHOLD_OFF,
SETTING_FREQ_HOPPING,
SETTING_TEST_CONTROL,
SETTING_HAPTIC_MASTER_GAIN_DB,
SETTING_THUMB_TOUCH_THRESH,
SETTING_DEVICE_POWER_STATUS,
SETTING_HAPTIC_INTENSITY,
// 80
SETTING_STABILIZER_ENABLED,
SETTING_TIMP_MODE_MTE,
SETTING_COUNT,
// This is a special setting value use for callbacks and should not be set/get explicitly.
@ -461,6 +543,7 @@ typedef enum
HAPTIC_PULSE_NORMAL = 0x0000,
HAPTIC_PULSE_HIGH_PRIORITY = 0x0001,
HAPTIC_PULSE_VERY_HIGH_PRIORITY = 0x0002,
HAPTIC_PULSE_IGNORE_USER_PREFS = 0x0003,
} SettingHapticPulseFlags;
typedef struct

View File

@ -32,6 +32,13 @@ typedef struct
unsigned char length;
} FeatureReportHeader;
// Generic controller settings structure
typedef struct
{
unsigned char settingNum;
unsigned short settingValue;
} ControllerSetting;
// Generic controller attribute structure
typedef struct
{
@ -39,12 +46,89 @@ typedef struct
uint32_t attributeValue;
} ControllerAttribute;
// Generic controller settings structure
typedef struct
{
ControllerSetting settings[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerSetting ) ];
} MsgSetSettingsValues, MsgGetSettingsValues, MsgGetSettingsDefaults, MsgGetSettingsMaxs;
// Generic controller settings structure
typedef struct
{
ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ];
} MsgGetAttributes;
typedef struct
{
unsigned char attributeTag;
char attributeValue[20];
} MsgGetStringAttribute;
typedef struct
{
unsigned char mode;
} MsgSetControllerMode;
// Trigger a haptic pulse
typedef struct {
unsigned char which_pad;
unsigned short pulse_duration;
unsigned short pulse_interval;
unsigned short pulse_count;
short dBgain;
unsigned char priority;
} MsgFireHapticPulse;
typedef struct {
uint8_t mode;
} MsgHapticSetMode;
typedef enum {
HAPTIC_TYPE_OFF,
HAPTIC_TYPE_TICK,
HAPTIC_TYPE_CLICK,
HAPTIC_TYPE_TONE,
HAPTIC_TYPE_RUMBLE,
HAPTIC_TYPE_NOISE,
HAPTIC_TYPE_SCRIPT,
HAPTIC_TYPE_LOG_SWEEP,
} haptic_type_t;
typedef enum {
HAPTIC_INTENSITY_SYSTEM,
HAPTIC_INTENSITY_SHORT,
HAPTIC_INTENSITY_MEDIUM,
HAPTIC_INTENSITY_LONG,
HAPTIC_INTENSITY_INSANE,
} haptic_intensity_t;
typedef struct {
uint8_t side; // 0x01 = L, 0x02 = R, 0x03 = Both
uint8_t cmd; // 0 = Off, 1 = tick, 2 = click, 3 = tone, 4 = rumble, 5 =
// rumble_noise, 6 = script, 7 = sweep,
uint8_t ui_intensity; // 0-4 (0 = default)
int8_t dBgain; // dB Can be positive (reasonable clipping / limiting will apply)
uint16_t freq; // Frequency of tone (if applicable)
int16_t dur_ms; // Duration of tone / rumble (if applicable) (neg = infinite)
uint16_t noise_intensity;
uint16_t lfo_freq; // Drives both tone and rumble geneators
uint8_t lfo_depth; // percentage, typically 100
uint8_t rand_tone_gain; // Randomize each LFO cycle's gain
uint8_t script_id; // Used w/ dBgain for scripted haptics
uint16_t lss_start_freq; // Used w/ Log Sine Sweep
uint16_t lss_end_freq; // Ditto
} MsgTriggerHaptic;
typedef struct {
uint8_t unRumbleType;
uint16_t unIntensity;
uint16_t unLeftMotorSpeed;
uint16_t unRightMotorSpeed;
int8_t nLeftGain;
int8_t nRightGain;
} MsgSimpleRumbleCmd;
// 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
@ -55,7 +139,17 @@ typedef struct
FeatureReportHeader header;
union
{
MsgGetAttributes getAttributes;
MsgSetSettingsValues setSettingsValues;
MsgGetSettingsValues getSettingsValues;
MsgGetSettingsMaxs getSettingsMaxs;
MsgGetSettingsDefaults getSettingsDefaults;
MsgGetAttributes getAttributes;
MsgSetControllerMode controllerMode;
MsgFireHapticPulse fireHapticPulse;
MsgGetStringAttribute getStringAttribute;
MsgHapticSetMode hapticMode;
MsgTriggerHaptic triggerHaptic;
MsgSimpleRumbleCmd simpleRumble;
} payload;
} FeatureReportMsg;
@ -77,6 +171,7 @@ typedef enum
ID_CONTROLLER_DEBUG2 = 5,
ID_CONTROLLER_SECONDARY_STATE = 6,
ID_CONTROLLER_BLE_STATE = 7,
ID_CONTROLLER_DECK_STATE = 9,
ID_CONTROLLER_MSG_COUNT
} ValveInReportMessageIDs;
@ -94,12 +189,12 @@ typedef struct
{
// If packet num matches that on your prior call, then the controller state hasn't been changed since
// your last call and there is no need to process it
uint32 unPacketNum;
Uint32 unPacketNum;
// Button bitmask and trigger data.
union
{
uint64 ulButtons;
Uint64 ulButtons;
struct
{
unsigned char _pad0[3];
@ -143,12 +238,12 @@ typedef struct
{
// If packet num matches that on your prior call, then the controller state hasn't been changed since
// your last call and there is no need to process it
uint32 unPacketNum;
Uint32 unPacketNum;
// Button bitmask and trigger data.
union
{
uint64 ulButtons;
Uint64 ulButtons;
struct
{
unsigned char _pad0[3];
@ -258,6 +353,66 @@ typedef struct
unsigned char ucBatteryLevel;
} SteamControllerStatusEvent_t;
// Deck State payload
typedef struct
{
// If packet num matches that on your prior call, then the controller
// state hasn't been changed since your last call and there is no need to
// process it
Uint32 unPacketNum;
// Button bitmask and trigger data.
union
{
Uint64 ulButtons;
struct
{
Uint32 ulButtonsL;
Uint32 ulButtonsH;
};
};
// Left pad coordinates
short sLeftPadX;
short sLeftPadY;
// Right pad coordinates
short sRightPadX;
short sRightPadY;
// Accelerometer values
short sAccelX;
short sAccelY;
short sAccelZ;
// Gyroscope values
short sGyroX;
short sGyroY;
short sGyroZ;
// Gyro quaternions
short sGyroQuatW;
short sGyroQuatX;
short sGyroQuatY;
short sGyroQuatZ;
// Uncalibrated trigger values
unsigned short sTriggerRawL;
unsigned short sTriggerRawR;
// Left stick values
short sLeftStickX;
short sLeftStickY;
// Right stick values
short sRightStickX;
short sRightStickY;
// Touchpad pressures
unsigned short sPressurePadLeft;
unsigned short sPressurePadRight;
} SteamDeckStatePacket_t;
typedef struct
{
ValveInReportHeader_t header;
@ -271,6 +426,7 @@ typedef struct
ValveControllerRawTrackpadImage_t rawPadImage;
SteamControllerWirelessEvent_t wirelessEvent;
SteamControllerStatusEvent_t statusEvent;
SteamDeckStatePacket_t deckState;
} payload;
} ValveInReport_t;

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -145,8 +145,8 @@ 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);
static void MaybeAddDevice(const char *path);
static void MaybeRemoveDevice(const char *path);
/* A linked list of available joysticks */
typedef struct SDL_joylist_item
@ -156,6 +156,7 @@ typedef struct SDL_joylist_item
char *name; /* "SideWinder 3D Pro" or whatever */
SDL_JoystickGUID guid;
dev_t devnum;
int steam_virtual_gamepad_slot;
struct joystick_hwdata *hwdata;
struct SDL_joylist_item *next;
@ -176,10 +177,10 @@ typedef struct SDL_sensorlist_item
} SDL_sensorlist_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;
static SDL_sensorlist_item *SDL_sensorlist = NULL;
static SDL_joylist_item *SDL_joylist SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static SDL_joylist_item *SDL_joylist_tail SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static int numjoysticks SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static SDL_sensorlist_item *SDL_sensorlist SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static int inotify_fd = -1;
static Uint64 last_joy_detect_time;
@ -219,6 +220,23 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version,
}
#endif /* SDL_JOYSTICK_HIDAPI */
static SDL_bool GetSteamVirtualGamepadSlot(int fd, int *slot)
{
char name[128];
if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) {
const char *digits = SDL_strstr(name, "pad ");
if (digits) {
digits += 4;
if (SDL_isdigit(*digits)) {
*slot = SDL_atoi(digits);
return SDL_TRUE;
}
}
}
return SDL_FALSE;
}
static int GuessDeviceClass(int fd)
{
unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 };
@ -259,23 +277,25 @@ static int GuessIsSensor(int fd)
return 0;
}
static int IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid)
static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vendor_return, Uint16 *product_return, SDL_JoystickGUID *guid)
{
struct input_id inpid;
char *name;
char product_string[128];
int class = 0;
if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) >= 0) {
SDL_zero(inpid);
SDL_zero(inpid);
#ifdef SDL_USE_LIBUDEV
SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version);
SDL_UDEV_GetProductInfo(path, &inpid.vendor, &inpid.product, &inpid.version, &class);
#endif
} else {
if (ioctl(fd, JSIOCGNAME(sizeof(product_string)), product_string) <= 0) {
/* 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)) {
if (enumeration_method != ENUMERATION_LIBUDEV &&
!(class & SDL_UDEV_DEVICE_JOYSTICK) && ( class || !GuessIsJoystick(fd))) {
return 0;
}
/* Could have vendor and product already from udev, but should agree with evdev */
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
return 0;
}
@ -286,7 +306,7 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick
}
name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string);
if (name == NULL) {
if (!name) {
return 0;
}
@ -305,13 +325,15 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick
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
*guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, name, 0, 0);
*guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, NULL, product_string, 0, 0);
if (SDL_ShouldIgnoreJoystick(name, *guid)) {
SDL_free(name);
return 0;
}
*name_return = name;
*vendor_return = inpid.vendor;
*product_return = inpid.product;
return 1;
}
@ -335,7 +357,7 @@ static int IsSensor(const char *path, int fd)
#ifdef SDL_USE_LIBUDEV
static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
{
if (devpath == NULL) {
if (!devpath) {
return;
}
@ -384,67 +406,75 @@ static void FreeSensorlistItem(SDL_sensorlist_item *item)
SDL_free(item);
}
static int MaybeAddDevice(const char *path)
static void MaybeAddDevice(const char *path)
{
struct stat sb;
int fd = -1;
char *name = NULL;
Uint16 vendor, product;
SDL_JoystickGUID guid;
SDL_joylist_item *item;
SDL_sensorlist_item *item_sensor;
if (path == NULL) {
return -1;
if (!path) {
return;
}
if (stat(path, &sb) == -1) {
return -1;
return;
}
SDL_LockJoysticks();
/* Check to make sure it's not already in list. */
for (item = SDL_joylist; item != NULL; item = item->next) {
for (item = SDL_joylist; item; item = item->next) {
if (sb.st_rdev == item->devnum) {
return -1; /* already have this one */
goto done; /* already have this one */
}
}
for (item_sensor = SDL_sensorlist; item_sensor != NULL; item_sensor = item_sensor->next) {
for (item_sensor = SDL_sensorlist; item_sensor; item_sensor = item_sensor->next) {
if (sb.st_rdev == item_sensor->devnum) {
return -1; /* already have this one */
goto done; /* already have this one */
}
}
fd = open(path, O_RDONLY | O_CLOEXEC, 0);
if (fd < 0) {
return -1;
goto done;
}
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Checking %s\n", path);
#endif
if (IsJoystick(path, fd, &name, &guid)) {
if (IsJoystick(path, fd, &name, &vendor, &product, &guid)) {
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("found joystick: %s\n", path);
#endif
close(fd);
item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item));
if (item == NULL) {
if (!item) {
SDL_free(name);
return -1;
goto done;
}
item->devnum = sb.st_rdev;
item->steam_virtual_gamepad_slot = -1;
item->path = SDL_strdup(path);
item->name = name;
item->guid = guid;
if ((item->path == NULL) || (item->name == NULL)) {
FreeJoylistItem(item);
return -1;
if (vendor == USB_VENDOR_VALVE &&
product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
GetSteamVirtualGamepadSlot(fd, &item->steam_virtual_gamepad_slot);
}
item->device_instance = SDL_GetNextJoystickInstanceID();
if (SDL_joylist_tail == NULL) {
if ((!item->path) || (!item->name)) {
FreeJoylistItem(item);
goto done;
}
item->device_instance = SDL_GetNextObjectID();
if (!SDL_joylist_tail) {
SDL_joylist = SDL_joylist_tail = item;
} else {
SDL_joylist_tail->next = item;
@ -455,42 +485,46 @@ static int MaybeAddDevice(const char *path)
++numjoysticks;
SDL_PrivateJoystickAdded(item->device_instance);
return numjoysticks;
goto done;
}
if (IsSensor(path, fd)) {
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("found sensor: %s\n", path);
#endif
close(fd);
item_sensor = (SDL_sensorlist_item *)SDL_calloc(1, sizeof(SDL_sensorlist_item));
if (item_sensor == NULL) {
return -1;
if (!item_sensor) {
goto done;
}
item_sensor->devnum = sb.st_rdev;
item_sensor->path = SDL_strdup(path);
if (item_sensor->path == NULL) {
if (!item_sensor->path) {
FreeSensorlistItem(item_sensor);
return -1;
goto done;
}
item_sensor->next = SDL_sensorlist;
SDL_sensorlist = item_sensor;
return -1;
goto done;
}
close(fd);
return -1;
done:
if (fd >= 0) {
close(fd);
}
SDL_UnlockJoysticks();
}
static void RemoveJoylistItem(SDL_joylist_item *item, SDL_joylist_item *prev)
{
SDL_AssertJoysticksLocked();
if (item->hwdata) {
item->hwdata->item = NULL;
}
if (prev != NULL) {
if (prev) {
prev->next = item->next;
} else {
SDL_assert(SDL_joylist == item);
@ -510,11 +544,13 @@ static void RemoveJoylistItem(SDL_joylist_item *item, SDL_joylist_item *prev)
static void RemoveSensorlistItem(SDL_sensorlist_item *item, SDL_sensorlist_item *prev)
{
SDL_AssertJoysticksLocked();
if (item->hwdata) {
item->hwdata->item_sensor = NULL;
}
if (prev != NULL) {
if (prev) {
prev->next = item->next;
} else {
SDL_assert(SDL_sensorlist == item);
@ -526,50 +562,53 @@ static void RemoveSensorlistItem(SDL_sensorlist_item *item, SDL_sensorlist_item
FreeSensorlistItem(item);
}
static int MaybeRemoveDevice(const char *path)
static void MaybeRemoveDevice(const char *path)
{
SDL_joylist_item *item;
SDL_joylist_item *prev = NULL;
SDL_sensorlist_item *item_sensor;
SDL_sensorlist_item *prev_sensor = NULL;
if (path == NULL) {
return -1;
if (!path) {
return;
}
for (item = SDL_joylist; item != NULL; item = item->next) {
SDL_LockJoysticks();
for (item = SDL_joylist; item; item = item->next) {
/* found it, remove it. */
if (SDL_strcmp(path, item->path) == 0) {
const int retval = item->device_instance;
RemoveJoylistItem(item, prev);
return retval;
goto done;
}
prev = item;
}
for (item_sensor = SDL_sensorlist; item_sensor != NULL; item_sensor = item_sensor->next) {
for (item_sensor = SDL_sensorlist; item_sensor; item_sensor = item_sensor->next) {
/* found it, remove it. */
if (SDL_strcmp(path, item_sensor->path) == 0) {
RemoveSensorlistItem(item_sensor, prev_sensor);
return -1;
goto done;
}
prev_sensor = item_sensor;
}
return -1;
done:
SDL_UnlockJoysticks();
}
static void HandlePendingRemovals(void)
{
SDL_joylist_item *prev = NULL;
SDL_joylist_item *item = SDL_joylist;
SDL_joylist_item *item = NULL;
SDL_sensorlist_item *prev_sensor = NULL;
SDL_sensorlist_item *item_sensor = SDL_sensorlist;
SDL_sensorlist_item *item_sensor = NULL;
while (item != NULL) {
SDL_AssertJoysticksLocked();
item = SDL_joylist;
while (item) {
if (item->hwdata && item->hwdata->gone) {
RemoveJoylistItem(item, prev);
if (prev != NULL) {
if (prev) {
item = prev->next;
} else {
item = SDL_joylist;
@ -580,11 +619,12 @@ static void HandlePendingRemovals(void)
}
}
while (item_sensor != NULL) {
item_sensor = SDL_sensorlist;
while (item_sensor) {
if (item_sensor->hwdata && item_sensor->hwdata->sensor_gone) {
RemoveSensorlistItem(item_sensor, prev_sensor);
if (prev_sensor != NULL) {
if (prev_sensor) {
item_sensor = prev_sensor->next;
} else {
item_sensor = SDL_sensorlist;
@ -601,7 +641,7 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG
SDL_joylist_item *item;
item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item));
if (item == NULL) {
if (!item) {
return SDL_FALSE;
}
@ -610,13 +650,14 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG
item->guid = guid;
item->m_bSteamController = SDL_TRUE;
if ((item->path == NULL) || (item->name == NULL)) {
if ((!item->path) || (!item->name)) {
FreeJoylistItem(item);
return SDL_FALSE;
}
*device_instance = item->device_instance = SDL_GetNextJoystickInstanceID();
if (SDL_joylist_tail == NULL) {
*device_instance = item->device_instance = SDL_GetNextObjectID();
SDL_LockJoysticks();
if (!SDL_joylist_tail) {
SDL_joylist = SDL_joylist_tail = item;
} else {
SDL_joylist_tail->next = item;
@ -627,6 +668,7 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG
++numjoysticks;
SDL_PrivateJoystickAdded(item->device_instance);
SDL_UnlockJoysticks();
return SDL_TRUE;
}
@ -636,14 +678,16 @@ static void SteamControllerDisconnectedCallback(SDL_JoystickID device_instance)
SDL_joylist_item *item;
SDL_joylist_item *prev = NULL;
for (item = SDL_joylist; item != NULL; item = item->next) {
SDL_LockJoysticks();
for (item = SDL_joylist; item; item = item->next) {
/* found it, remove it. */
if (item->device_instance == device_instance) {
RemoveJoylistItem(item, prev);
return;
break;
}
prev = item;
}
SDL_UnlockJoysticks();
}
static int StrHasPrefix(const char *string, const char *prefix)
@ -817,6 +861,89 @@ static int SDLCALL sort_entries(const void *_a, const void *_b)
return numA - numB;
}
typedef struct
{
char *path;
int slot;
} VirtualGamepadEntry;
static int SDLCALL sort_virtual_gamepads(const void *_a, const void *_b)
{
const VirtualGamepadEntry *a = (const VirtualGamepadEntry *)_a;
const VirtualGamepadEntry *b = (const VirtualGamepadEntry *)_b;
return a->slot - b->slot;
}
static void LINUX_ScanSteamVirtualGamepads(void)
{
int i, count;
int fd;
struct dirent **entries = NULL;
char path[PATH_MAX];
struct input_id inpid;
int num_virtual_gamepads = 0;
int virtual_gamepad_slot;
VirtualGamepadEntry *virtual_gamepads = NULL;
count = scandir("/dev/input", &entries, filter_entries, NULL);
for (i = 0; i < count; ++i) {
(void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
fd = open(path, O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (ioctl(fd, EVIOCGID, &inpid) == 0 &&
inpid.vendor == USB_VENDOR_VALVE &&
inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD &&
GetSteamVirtualGamepadSlot(fd, &virtual_gamepad_slot)) {
VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads));
if (new_virtual_gamepads) {
VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads];
entry->path = SDL_strdup(path);
entry->slot = virtual_gamepad_slot;
if (entry->path) {
virtual_gamepads = new_virtual_gamepads;
++num_virtual_gamepads;
} else {
SDL_free(entry->path);
SDL_free(new_virtual_gamepads);
}
}
}
close(fd);
}
free(entries[i]); /* This should NOT be SDL_free() */
}
free(entries); /* This should NOT be SDL_free() */
if (num_virtual_gamepads > 1) {
SDL_qsort(virtual_gamepads, num_virtual_gamepads, sizeof(*virtual_gamepads), sort_virtual_gamepads);
}
for (i = 0; i < num_virtual_gamepads; ++i) {
MaybeAddDevice(virtual_gamepads[i].path);
SDL_free(virtual_gamepads[i].path);
}
SDL_free(virtual_gamepads);
}
static void LINUX_ScanInputDevices(void)
{
int i, count;
struct dirent **entries = NULL;
char path[PATH_MAX];
count = scandir("/dev/input", &entries, filter_entries, NULL);
if (count > 1) {
SDL_qsort(entries, count, sizeof(*entries), sort_entries);
}
for (i = 0; i < count; ++i) {
(void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
MaybeAddDevice(path);
free(entries[i]); /* This should NOT be SDL_free() */
}
free(entries); /* This should NOT be SDL_free() */
}
static void LINUX_FallbackJoystickDetect(void)
{
const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
@ -827,21 +954,10 @@ static void LINUX_FallbackJoystickDetect(void)
/* Opening input devices can generate synchronous device I/O, so avoid it if we can */
if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
int i, count;
struct dirent **entries = NULL;
char path[PATH_MAX];
/* Look for Steam virtual gamepads first, and sort by Steam controller slot */
LINUX_ScanSteamVirtualGamepads();
count = scandir("/dev/input", &entries, filter_entries, NULL);
if (count > 1) {
SDL_qsort(entries, count, sizeof(*entries), sort_entries);
}
for (i = 0; i < count; ++i) {
(void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
MaybeAddDevice(path);
free(entries[i]); /* This should NOT be SDL_free() */
}
free(entries); /* This should NOT be SDL_free() */
LINUX_ScanInputDevices();
last_input_dir_mtime = sb.st_mtime;
}
@ -880,13 +996,13 @@ static int LINUX_JoystickInit(void)
enumeration_method = ENUMERATION_UNSET;
/* First see if the user specified one or more joysticks to use */
if (devices != NULL) {
if (devices) {
char *envcopy, *envpath, *delim;
envcopy = SDL_strdup(devices);
envpath = envcopy;
while (envpath != NULL) {
while (envpath) {
delim = SDL_strchr(envpath, ':');
if (delim != NULL) {
if (delim) {
*delim++ = '\0';
}
MaybeAddDevice(envpath);
@ -969,17 +1085,22 @@ static int LINUX_JoystickInit(void)
static int LINUX_JoystickGetCount(void)
{
SDL_AssertJoysticksLocked();
return numjoysticks;
}
static SDL_joylist_item *GetJoystickByDevIndex(int device_index)
{
SDL_joylist_item *item = SDL_joylist;
SDL_joylist_item *item;
SDL_AssertJoysticksLocked();
if ((device_index < 0) || (device_index >= numjoysticks)) {
return NULL;
}
item = SDL_joylist;
while (device_index > 0) {
SDL_assert(item != NULL);
device_index--;
@ -999,6 +1120,11 @@ static const char *LINUX_JoystickGetDevicePath(int device_index)
return GetJoystickByDevIndex(device_index)->path;
}
static int LINUX_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return GetJoystickByDevIndex(device_index)->steam_virtual_gamepad_slot;
}
static int LINUX_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -1028,7 +1154,7 @@ static int allocate_hatdata(SDL_Joystick *joystick)
joystick->hwdata->hats =
(struct hwdata_hat *)SDL_malloc(joystick->nhats *
sizeof(struct hwdata_hat));
if (joystick->hwdata->hats == NULL) {
if (!joystick->hwdata->hats) {
return -1;
}
for (i = 0; i < joystick->nhats; ++i) {
@ -1047,7 +1173,7 @@ static SDL_bool GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct
* other continuous analog axis, so we have to guess. */
/* If both axes are missing, they're not anything. */
if (absinfo_x == NULL && absinfo_y == NULL) {
if (!absinfo_x && !absinfo_y) {
return SDL_FALSE;
}
@ -1057,12 +1183,12 @@ static SDL_bool GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct
}
/* If both axes have ranges constrained between -1 and 1, they're definitely digital. */
if ((absinfo_x == NULL || (absinfo_x->minimum == -1 && absinfo_x->maximum == 1)) && (absinfo_y == NULL || (absinfo_y->minimum == -1 && absinfo_y->maximum == 1))) {
if ((!absinfo_x || (absinfo_x->minimum == -1 && absinfo_x->maximum == 1)) && (!absinfo_y || (absinfo_y->minimum == -1 && absinfo_y->maximum == 1))) {
return SDL_TRUE;
}
/* If both axes lack fuzz, flat, and resolution values, they're probably digital. */
if ((absinfo_x == NULL || (!absinfo_x->fuzz && !absinfo_x->flat && !absinfo_x->resolution)) && (absinfo_y == NULL || (!absinfo_y->fuzz && !absinfo_y->flat && !absinfo_y->resolution))) {
if ((!absinfo_x || (!absinfo_x->fuzz && !absinfo_x->flat && !absinfo_x->resolution)) && (!absinfo_y || (!absinfo_y->fuzz && !absinfo_y->flat && !absinfo_y->resolution))) {
return SDL_TRUE;
}
@ -1261,9 +1387,11 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor)
/* Sensors are only available through the new unified event API */
if (fd_sensor >= 0 && (ioctl(fd_sensor, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0)) {
if (test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) && test_bit(ABS_Z, absbit)) {
joystick->hwdata->has_accelerometer = SDL_TRUE;
for (i = 0; i < 3; ++i) {
struct input_absinfo absinfo;
if (ioctl(fd_sensor, EVIOCGABS(ABS_X + i), &absinfo) < 0) {
joystick->hwdata->has_accelerometer = SDL_FALSE;
break; /* do not report an accelerometer if we can't read all axes */
}
joystick->hwdata->accelerometer_scale[i] = absinfo.resolution;
@ -1274,14 +1402,15 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor)
absinfo.fuzz, absinfo.flat, absinfo.resolution);
#endif /* DEBUG_INPUT_EVENTS */
}
joystick->hwdata->has_accelerometer = SDL_TRUE;
}
if (test_bit(ABS_RX, absbit) && test_bit(ABS_RY, absbit) && test_bit(ABS_RZ, absbit)) {
joystick->hwdata->has_gyro = SDL_TRUE;
for (i = 0; i < 3; ++i) {
struct input_absinfo absinfo;
if (ioctl(fd_sensor, EVIOCGABS(ABS_RX + i), &absinfo) < 0) {
break; /* do not report an gyro if we can't read all axes */
joystick->hwdata->has_gyro = SDL_FALSE;
break; /* do not report a gyro if we can't read all axes */
}
joystick->hwdata->gyro_scale[i] = absinfo.resolution;
#ifdef DEBUG_INPUT_EVENTS
@ -1291,7 +1420,6 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor)
absinfo.fuzz, absinfo.flat, absinfo.resolution);
#endif /* DEBUG_INPUT_EVENTS */
}
joystick->hwdata->has_gyro = SDL_TRUE;
}
}
@ -1347,19 +1475,19 @@ static int PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item,
return SDL_SetError("Unable to open %s", item->path);
}
/* If opening sensor fail, continue with buttons and axes only */
if (item_sensor != NULL) {
if (item_sensor) {
fd_sensor = open(item_sensor->path, O_RDONLY | O_CLOEXEC, 0);
}
joystick->hwdata->fd = fd;
joystick->hwdata->fd_sensor = fd_sensor;
joystick->hwdata->fname = SDL_strdup(item->path);
if (joystick->hwdata->fname == NULL) {
if (!joystick->hwdata->fname) {
close(fd);
if (fd_sensor >= 0) {
close(fd_sensor);
}
return SDL_OutOfMemory();
return -1;
}
/* Set the joystick to non-blocking read mode */
@ -1380,7 +1508,9 @@ static SDL_sensorlist_item *GetSensor(SDL_joylist_item *item)
char uniq_item[128];
int fd_item = -1;
if (item == NULL || SDL_sensorlist == NULL) {
SDL_AssertJoysticksLocked();
if (!item || !SDL_sensorlist) {
return NULL;
}
@ -1397,10 +1527,10 @@ static SDL_sensorlist_item *GetSensor(SDL_joylist_item *item)
SDL_Log("Joystick UNIQ: %s\n", uniq_item);
#endif /* DEBUG_INPUT_EVENTS */
for (item_sensor = SDL_sensorlist; item_sensor != NULL; item_sensor = item_sensor->next) {
for (item_sensor = SDL_sensorlist; item_sensor; item_sensor = item_sensor->next) {
char uniq_sensor[128];
int fd_sensor = -1;
if (item_sensor->hwdata != NULL) {
if (item_sensor->hwdata) {
/* already associated with another joystick */
continue;
}
@ -1433,22 +1563,24 @@ static SDL_sensorlist_item *GetSensor(SDL_joylist_item *item)
*/
static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index)
{
SDL_joylist_item *item = GetJoystickByDevIndex(device_index);
SDL_sensorlist_item *item_sensor = GetSensor(item);
SDL_joylist_item *item;
SDL_sensorlist_item *item_sensor;
SDL_AssertJoysticksLocked();
if (item == NULL) {
item = GetJoystickByDevIndex(device_index);
if (!item) {
return SDL_SetError("No such device");
}
joystick->instance_id = item->device_instance;
joystick->hwdata = (struct joystick_hwdata *)
SDL_calloc(1, sizeof(*joystick->hwdata));
if (joystick->hwdata == NULL) {
return SDL_OutOfMemory();
if (!joystick->hwdata) {
return -1;
}
item_sensor = GetSensor(item);
if (PrepareJoystickHwdata(joystick, item, item_sensor) == -1) {
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
@ -1458,7 +1590,7 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index)
SDL_assert(item->hwdata == NULL);
SDL_assert(!item_sensor || item_sensor->hwdata == NULL);
item->hwdata = joystick->hwdata;
if (item_sensor != NULL) {
if (item_sensor) {
item_sensor->hwdata = joystick->hwdata;
}
@ -1563,7 +1695,9 @@ static int LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enab
}
if (enabled) {
SDL_assert(joystick->hwdata->item_sensor);
if (!joystick->hwdata->item_sensor) {
return SDL_SetError("Sensors unplugged.");
}
joystick->hwdata->fd_sensor = open(joystick->hwdata->item_sensor->path, O_RDONLY | O_CLOEXEC, 0);
if (joystick->hwdata->fd_sensor < 0) {
return SDL_SetError("Couldn't open sensor file %s.", joystick->hwdata->item_sensor->path);
@ -2047,6 +2181,8 @@ static void LINUX_JoystickQuit(void)
SDL_sensorlist_item *item_sensor = NULL;
SDL_sensorlist_item *next_sensor = NULL;
SDL_AssertJoysticksLocked();
if (inotify_fd >= 0) {
close(inotify_fd);
inotify_fd = -1;
@ -2116,18 +2252,16 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap
/* We temporarily open the device to check how it's configured. Make
a fake SDL_Joystick object to do so. */
joystick = (SDL_Joystick *)SDL_calloc(sizeof(*joystick), 1);
joystick->magic = &SDL_joystick_magic;
if (joystick == NULL) {
SDL_OutOfMemory();
if (!joystick) {
return SDL_FALSE;
}
joystick->magic = &SDL_joystick_magic;
SDL_memcpy(&joystick->guid, &item->guid, sizeof(item->guid));
joystick->hwdata = (struct joystick_hwdata *)
SDL_calloc(1, sizeof(*joystick->hwdata));
if (joystick->hwdata == NULL) {
if (!joystick->hwdata) {
SDL_free(joystick);
SDL_OutOfMemory();
return SDL_FALSE;
}
@ -2564,6 +2698,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = {
LINUX_JoystickDetect,
LINUX_JoystickGetDeviceName,
LINUX_JoystickGetDevicePath,
LINUX_JoystickGetDeviceSteamVirtualGamepadSlot,
LINUX_JoystickGetDevicePlayerIndex,
LINUX_JoystickSetDevicePlayerIndex,
LINUX_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -36,13 +36,23 @@
This correction is applied to axis values
so they fit better in SDL's value range.
*/
#define CORRECT_AXIS_X(X) ((X * SDL_JOYSTICK_AXIS_MAX) / 160)
static inline int Correct_Axis_X(int X) {
if (X > 160) {
return SDL_JOYSTICK_AXIS_MAX;
}
else if (X < -160) {
return -SDL_JOYSTICK_AXIS_MAX;
}
return (X * SDL_JOYSTICK_AXIS_MAX) / 160;
}
/*
The Y axis needs to be flipped because SDL's "up"
is reversed compared to libctru's "up"
*/
#define CORRECT_AXIS_Y(Y) CORRECT_AXIS_X(-Y)
static inline int Correct_Axis_Y(int Y) {
return Correct_Axis_X(-Y);
}
static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick);
static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick);
@ -73,7 +83,7 @@ static SDL_JoystickGUID N3DS_JoystickGetDeviceGUID(int device_index)
static SDL_JoystickID N3DS_JoystickGetDeviceInstanceID(int device_index)
{
return device_index;
return device_index + 1;
}
static int N3DS_JoystickOpen(SDL_Joystick *joystick, int device_index)
@ -141,12 +151,12 @@ static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick)
if (previous_state.dx != current_state.dx) {
SDL_SendJoystickAxis(timestamp, joystick,
0,
CORRECT_AXIS_X(current_state.dx));
Correct_Axis_X(current_state.dx));
}
if (previous_state.dy != current_state.dy) {
SDL_SendJoystickAxis(timestamp, joystick,
1,
CORRECT_AXIS_Y(current_state.dy));
Correct_Axis_Y(current_state.dy));
}
previous_state = current_state;
}
@ -159,12 +169,12 @@ static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick)
if (previous_state.dx != current_state.dx) {
SDL_SendJoystickAxis(timestamp, joystick,
2,
CORRECT_AXIS_X(current_state.dx));
Correct_Axis_X(current_state.dx));
}
if (previous_state.dy != current_state.dy) {
SDL_SendJoystickAxis(timestamp, joystick,
3,
CORRECT_AXIS_Y(current_state.dy));
Correct_Axis_Y(current_state.dy));
}
previous_state = current_state;
}
@ -221,6 +231,11 @@ static const char *N3DS_JoystickGetDevicePath(int device_index)
return NULL;
}
static int N3DS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int N3DS_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -261,6 +276,7 @@ SDL_JoystickDriver SDL_N3DS_JoystickDriver = {
.Detect = N3DS_JoystickDetect,
.GetDeviceName = N3DS_JoystickGetDeviceName,
.GetDevicePath = N3DS_JoystickGetDevicePath,
.GetDeviceSteamVirtualGamepadSlot = N3DS_JoystickGetDeviceSteamVirtualGamepadSlot,
.GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex,
.SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex,
.GetDeviceGUID = N3DS_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -157,6 +157,12 @@ static const char *PS2_JoystickGetDevicePath(int index)
return NULL;
}
/* Function to get the Steam virtual gamepad slot of a joystick */
static int PS2_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
/* Function to get the player index of a joystick */
static int PS2_JoystickGetDevicePlayerIndex(int device_index)
{
@ -179,7 +185,7 @@ static SDL_JoystickGUID PS2_JoystickGetDeviceGUID(int device_index)
/* Function to get the current instance id of the joystick located at device_index */
static SDL_JoystickID PS2_JoystickGetDeviceInstanceID(int device_index)
{
return device_index;
return device_index + 1;
}
/* Function to open a joystick for use.
@ -341,6 +347,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = {
PS2_JoystickDetect,
PS2_JoystickGetDeviceName,
PS2_JoystickGetDevicePath,
PS2_JoystickGetDeviceSteamVirtualGamepadSlot,
PS2_JoystickGetDevicePlayerIndex,
PS2_JoystickSetDevicePlayerIndex,
PS2_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -121,6 +121,11 @@ static const char *PSP_JoystickGetDevicePath(int index)
return NULL;
}
static int PSP_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int PSP_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -140,7 +145,7 @@ static SDL_JoystickGUID PSP_JoystickGetDeviceGUID(int device_index)
/* Function to perform the mapping from device index to the instance id for this index */
static SDL_JoystickID PSP_JoystickGetDeviceInstanceID(int device_index)
{
return device_index;
return device_index + 1;
}
/* Function to open a joystick for use.
@ -253,6 +258,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = {
PSP_JoystickDetect,
PSP_JoystickGetDeviceName,
PSP_JoystickGetDevicePath,
PSP_JoystickGetDeviceSteamVirtualGamepadSlot,
PSP_JoystickGetDevicePlayerIndex,
PSP_JoystickSetDevicePlayerIndex,
PSP_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -33,11 +33,13 @@
#define USB_VENDOR_DRAGONRISE 0x0079
#define USB_VENDOR_GOOGLE 0x18d1
#define USB_VENDOR_HORI 0x0f0d
#define USB_VENDOR_HP 0x03f0
#define USB_VENDOR_HYPERKIN 0x2e24
#define USB_VENDOR_LOGITECH 0x046d
#define USB_VENDOR_MADCATZ 0x0738
#define USB_VENDOR_MICROSOFT 0x045e
#define USB_VENDOR_NACON 0x146b
#define USB_VENDOR_NACON_ALT 0x3285
#define USB_VENDOR_NINTENDO 0x057e
#define USB_VENDOR_NVIDIA 0x0955
#define USB_VENDOR_PDP 0x0e6f
@ -54,20 +56,27 @@
#define USB_VENDOR_VALVE 0x28de
#define USB_VENDOR_ZEROPLUS 0x0c12
#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER 0x2002
#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER1 0x2002 /* Ultimate Wired Controller for Xbox */
#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER2 0x3106 /* Ultimate Wireless / Pro 2 Wired Controller */
#define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419
#define USB_PRODUCT_ASTRO_C40_XBOX360 0x0024
#define USB_PRODUCT_BACKBONE_ONE_IOS 0x0103
#define USB_PRODUCT_BACKBONE_ONE_IOS_PS5 0x0104
#define USB_PRODUCT_GAMESIR_G7 0x1001
#define USB_PRODUCT_GOOGLE_STADIA_CONTROLLER 0x9400
#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER 0x1846
#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 0x1843
#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2 0x1846
#define USB_PRODUCT_HORI_FIGHTING_COMMANDER_OCTA_SERIES_X 0x0150
#define USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X 0x014f
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS4 0x011c
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
#define USB_PRODUCT_LOGITECH_F310 0xc216
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRELESS 0x0d16
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED 0x0d19
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337
#define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019
#define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e
@ -112,6 +121,8 @@
#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_XBOX360_WIRELESS_RECEIVER_THIRDPARTY1 0x02a9
#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER_THIRDPARTY2 0x0291
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE 0x0b0a
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH 0x0b0c
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLE 0x0b21
@ -125,14 +136,15 @@
#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_HP_HYPERX 0x08b6
#define USB_PRODUCT_XBOX_SERIES_X_HP_HYPERX_RGB 0x07a0
#define USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW 0x02da
#define USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE 0x02d9
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 0x4001
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_MOGA_XP_ULTRA 0x890b
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA 0x4002
#define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6
#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 */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -66,7 +66,7 @@ static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata)
SDL_AssertJoysticksLocked();
if (hwdata == NULL) {
if (!hwdata) {
return;
}
@ -114,18 +114,18 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des
SDL_AssertJoysticksLocked();
if (desc == NULL) {
if (!desc) {
return SDL_InvalidParamError("desc");
}
if (desc->version != SDL_VIRTUAL_JOYSTICK_DESC_VERSION) {
/* Is this an old version that we can support? */
return SDL_SetError("Unsupported virtual joystick description version %d", desc->version);
return SDL_SetError("Unsupported virtual joystick description version %u", desc->version);
}
hwdata = SDL_calloc(1, sizeof(joystick_hwdata));
if (hwdata == NULL) {
if (!hwdata) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
return 0;
}
SDL_memcpy(&hwdata->desc, desc, sizeof(*desc));
@ -203,14 +203,14 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des
}
}
hwdata->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_VIRTUAL, hwdata->desc.vendor_id, hwdata->desc.product_id, 0, name, 'v', (Uint8)hwdata->desc.type);
hwdata->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_VIRTUAL, hwdata->desc.vendor_id, hwdata->desc.product_id, 0, NULL, name, 'v', (Uint8)hwdata->desc.type);
/* Allocate fields for different control-types */
if (hwdata->desc.naxes > 0) {
hwdata->axes = SDL_calloc(hwdata->desc.naxes, sizeof(Sint16));
if (!hwdata->axes) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
return 0;
}
/* Trigger axes are at minimum value at rest */
@ -225,19 +225,19 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des
hwdata->buttons = SDL_calloc(hwdata->desc.nbuttons, sizeof(Uint8));
if (!hwdata->buttons) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
return 0;
}
}
if (hwdata->desc.nhats > 0) {
hwdata->hats = SDL_calloc(hwdata->desc.nhats, sizeof(Uint8));
if (!hwdata->hats) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
return 0;
}
}
/* Allocate an instance ID for this device */
hwdata->instance_id = SDL_GetNextJoystickInstanceID();
hwdata->instance_id = SDL_GetNextObjectID();
/* Add virtual joystick to SDL-global lists */
if (g_VJoys) {
@ -257,7 +257,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des
int SDL_JoystickDetachVirtualInner(SDL_JoystickID instance_id)
{
joystick_hwdata *hwdata = VIRTUAL_HWDataForInstance(instance_id);
if (hwdata == NULL) {
if (!hwdata) {
return SDL_SetError("Virtual joystick data not found");
}
VIRTUAL_FreeHWData(hwdata);
@ -271,7 +271,7 @@ int SDL_SetJoystickVirtualAxisInner(SDL_Joystick *joystick, int axis, Sint16 val
SDL_AssertJoysticksLocked();
if (joystick == NULL || !joystick->hwdata) {
if (!joystick || !joystick->hwdata) {
SDL_UnlockJoysticks();
return SDL_SetError("Invalid joystick");
}
@ -293,7 +293,7 @@ int SDL_SetJoystickVirtualButtonInner(SDL_Joystick *joystick, int button, Uint8
SDL_AssertJoysticksLocked();
if (joystick == NULL || !joystick->hwdata) {
if (!joystick || !joystick->hwdata) {
SDL_UnlockJoysticks();
return SDL_SetError("Invalid joystick");
}
@ -315,7 +315,7 @@ int SDL_SetJoystickVirtualHatInner(SDL_Joystick *joystick, int hat, Uint8 value)
SDL_AssertJoysticksLocked();
if (joystick == NULL || !joystick->hwdata) {
if (!joystick || !joystick->hwdata) {
SDL_UnlockJoysticks();
return SDL_SetError("Invalid joystick");
}
@ -356,7 +356,7 @@ static void VIRTUAL_JoystickDetect(void)
static const char *VIRTUAL_JoystickGetDeviceName(int device_index)
{
joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
if (hwdata == NULL) {
if (!hwdata) {
return NULL;
}
return hwdata->name;
@ -367,6 +367,11 @@ static const char *VIRTUAL_JoystickGetDevicePath(int device_index)
return NULL;
}
static int VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int VIRTUAL_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -384,7 +389,7 @@ static void VIRTUAL_JoystickSetDevicePlayerIndex(int device_index, int player_in
static SDL_JoystickGUID VIRTUAL_JoystickGetDeviceGUID(int device_index)
{
joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
if (hwdata == NULL) {
if (!hwdata) {
SDL_JoystickGUID guid;
SDL_zero(guid);
return guid;
@ -395,7 +400,7 @@ static SDL_JoystickGUID VIRTUAL_JoystickGetDeviceGUID(int device_index)
static SDL_JoystickID VIRTUAL_JoystickGetDeviceInstanceID(int device_index)
{
joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
if (hwdata == NULL) {
if (!hwdata) {
return 0;
}
return hwdata->instance_id;
@ -408,7 +413,7 @@ static int VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index)
SDL_AssertJoysticksLocked();
hwdata = VIRTUAL_HWDataForIndex(device_index);
if (hwdata == NULL) {
if (!hwdata) {
return SDL_SetError("No such device");
}
joystick->instance_id = hwdata->instance_id;
@ -535,7 +540,7 @@ static void VIRTUAL_JoystickUpdate(SDL_Joystick *joystick)
SDL_AssertJoysticksLocked();
if (joystick == NULL) {
if (!joystick) {
return;
}
if (!joystick->hwdata) {
@ -589,22 +594,22 @@ static SDL_bool VIRTUAL_JoystickGetGamepadMapping(int device_index, SDL_GamepadM
return SDL_FALSE;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_A))) {
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_SOUTH))) {
out->a.kind = EMappingKind_Button;
out->a.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_B))) {
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_EAST))) {
out->b.kind = EMappingKind_Button;
out->b.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_X))) {
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_WEST))) {
out->x.kind = EMappingKind_Button;
out->x.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_Y))) {
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_NORTH))) {
out->y.kind = EMappingKind_Button;
out->y.target = current_button++;
}
@ -728,6 +733,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = {
VIRTUAL_JoystickDetect,
VIRTUAL_JoystickGetDeviceName,
VIRTUAL_JoystickGetDevicePath,
VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot,
VIRTUAL_JoystickGetDevicePlayerIndex,
VIRTUAL_JoystickSetDevicePlayerIndex,
VIRTUAL_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -151,7 +151,7 @@ void VITA_JoystickDetect()
/* Function to perform the mapping from device index to the instance id for this index */
SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index)
{
return device_index;
return device_index + 1;
}
const char *VITA_JoystickGetDeviceName(int index)
@ -181,6 +181,11 @@ const char *VITA_JoystickGetDevicePath(int index)
return NULL;
}
static int VITA_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int VITA_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -378,6 +383,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = {
VITA_JoystickDetect,
VITA_JoystickGetDeviceName,
VITA_JoystickGetDevicePath,
VITA_JoystickGetDeviceSteamVirtualGamepadSlot,
VITA_JoystickGetDevicePlayerIndex,
VITA_JoystickSetDevicePlayerIndex,
VITA_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -271,7 +271,7 @@ static SDL_bool QueryDeviceName(LPDIRECTINPUTDEVICE8 device, char **device_name)
{
DIPROPSTRING dipstr;
if (!device || device_name == NULL) {
if (!device || !device_name) {
return SDL_FALSE;
}
@ -293,7 +293,7 @@ static SDL_bool QueryDevicePath(LPDIRECTINPUTDEVICE8 device, char **device_path)
{
DIPROPGUIDANDPATH dippath;
if (!device || device_path == NULL) {
if (!device || !device_path) {
return SDL_FALSE;
}
@ -318,7 +318,7 @@ static SDL_bool QueryDeviceInfo(LPDIRECTINPUTDEVICE8 device, Uint16 *vendor_id,
{
DIPROPDWORD dipdw;
if (!device || vendor_id == NULL || product_id == NULL) {
if (!device || !vendor_id || !product_id) {
return SDL_FALSE;
}
@ -340,7 +340,7 @@ static SDL_bool QueryDeviceInfo(LPDIRECTINPUTDEVICE8 device, Uint16 *vendor_id,
void FreeRumbleEffectData(DIEFFECT *effect)
{
if (effect == NULL) {
if (!effect) {
return;
}
SDL_free(effect->rgdwAxes);
@ -356,7 +356,7 @@ DIEFFECT *CreateRumbleEffectData(Sint16 magnitude)
/* Create the effect */
effect = (DIEFFECT *)SDL_calloc(1, sizeof(*effect));
if (effect == NULL) {
if (!effect) {
return NULL;
}
effect->dwSize = sizeof(*effect);
@ -380,7 +380,7 @@ DIEFFECT *CreateRumbleEffectData(Sint16 magnitude)
effect->dwFlags |= DIEFF_CARTESIAN;
periodic = (DIPERIODIC *)SDL_calloc(1, sizeof(*periodic));
if (periodic == NULL) {
if (!periodic) {
FreeRumbleEffectData(effect);
return NULL;
}
@ -420,7 +420,7 @@ int SDL_DINPUT_JoystickInit(void)
/* Because we used CoCreateInstance, we need to Initialize it, first. */
instance = GetModuleHandle(NULL);
if (instance == NULL) {
if (!instance) {
IDirectInput8_Release(dinput);
dinput = NULL;
return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
@ -435,6 +435,17 @@ int SDL_DINPUT_JoystickInit(void)
return 0;
}
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path)
{
int slot = -1;
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
(void)SDL_sscanf(device_path, "\\\\?\\HID#VID_28DE&PID_11FF&IG_0%d", &slot);
}
return slot;
}
/* helper function for direct input, gets called for each connected joystick */
static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
{
@ -451,7 +462,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
char *hidPath = NULL;
char *name = NULL;
LPDIRECTINPUTDEVICE8 device = NULL;
DIDEVCAPS caps;
/* We are only supporting HID devices. */
CHECK(pDeviceInstance->dwDevType & DIDEVTYPE_HID);
@ -461,13 +471,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
CHECK(QueryDevicePath(device, &hidPath));
CHECK(QueryDeviceInfo(device, &vendor, &product));
/* Check to make sure the device has buttons and axes.
* This fixes incorrectly detecting the ROG CHAKRAM X mouse as a game controller on Windows 10
*/
caps.dwSize = sizeof(caps);
CHECK(SUCCEEDED(IDirectInputDevice8_GetCapabilities(device, &caps)));
CHECK(caps.dwAxes > 0 && caps.dwButtons > 0);
CHECK(!SDL_IsXInputDevice(vendor, product, hidPath));
pNewJoystick = *(JoyStick_DeviceData **)pContext;
@ -495,10 +498,10 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
pNewJoystick = pNewJoystick->pNext;
}
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData));
CHECK(pNewJoystick);
SDL_zerop(pNewJoystick);
pNewJoystick->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(vendor, product, hidPath);
SDL_strlcpy(pNewJoystick->path, hidPath, SDL_arraysize(pNewJoystick->path));
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));
@ -506,9 +509,9 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
CHECK(pNewJoystick->joystickname);
if (vendor && product) {
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 0, 0);
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 0, 0);
} else {
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, pNewJoystick->joystickname, 0, 0);
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, NULL, name, 0, 0);
}
CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));
@ -543,7 +546,7 @@ err:
void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
{
if (dinput == NULL) {
if (!dinput) {
return;
}
@ -595,7 +598,7 @@ SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor_id, Uint16 product_id, Uint16
{
Joystick_PresentData data;
if (dinput == NULL) {
if (!dinput) {
return SDL_FALSE;
}
@ -886,7 +889,7 @@ static int SDL_DINPUT_JoystickInitRumble(SDL_Joystick *joystick, Sint16 magnitud
/* Create the effect */
joystick->hwdata->ffeffect = CreateRumbleEffectData(magnitude);
if (!joystick->hwdata->ffeffect) {
return SDL_OutOfMemory();
return -1;
}
result = IDirectInputDevice8_CreateEffect(joystick->hwdata->InputDevice, &GUID_Sine,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -114,6 +114,7 @@ typedef struct SDL_RAWINPUT_Device
SDL_JoystickGUID guid;
SDL_bool is_xinput;
SDL_bool is_xboxone;
int steam_virtual_gamepad_slot;
PHIDP_PREPARSED_DATA preparsed_data;
HANDLE hDevice;
@ -249,10 +250,10 @@ static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint64 match_state
/* Bitwise map .RLDUWVQTS.KYXBA -> YXBA..WVQTKSRLDU */
(WORD)(match_state << 12 | (match_state & 0x0780) >> 1 | (match_state & 0x0010) << 1 | (match_state & 0x0040) >> 2 | (match_state & 0x7800) >> 11);
/* Explicit
((match_state & (1<<SDL_GAMEPAD_BUTTON_A)) ? XINPUT_GAMEPAD_A : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_B)) ? XINPUT_GAMEPAD_B : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_X)) ? XINPUT_GAMEPAD_X : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_Y)) ? XINPUT_GAMEPAD_Y : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_SOUTH)) ? XINPUT_GAMEPAD_A : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_EAST)) ? XINPUT_GAMEPAD_B : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_WEST)) ? XINPUT_GAMEPAD_X : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_NORTH)) ? XINPUT_GAMEPAD_Y : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_BACK)) ? XINPUT_GAMEPAD_BACK : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_START)) ? XINPUT_GAMEPAD_START : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_LEFT_STICK)) ? XINPUT_GAMEPAD_LEFT_THUMB : 0) |
@ -289,10 +290,10 @@ static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint64 match_state
/* RStick/LStick (QT) RShould/LShould (WV) DPad R/L/D/U YXBA bac(K) (S)tart */
(match_state & 0x0180) << 5 | (match_state & 0x0600) << 1 | (match_state & 0x7800) >> 5 | (match_state & 0x000F) << 2 | (match_state & 0x0010) >> 3 | (match_state & 0x0040) >> 6;
/* Explicit
((match_state & (1<<SDL_GAMEPAD_BUTTON_A)) ? GamepadButtons_A : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_B)) ? GamepadButtons_B : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_X)) ? GamepadButtons_X : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_Y)) ? GamepadButtons_Y : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_SOUTH)) ? GamepadButtons_A : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_EAST)) ? GamepadButtons_B : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_WEST)) ? GamepadButtons_X : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_NORTH)) ? GamepadButtons_Y : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_BACK)) ? GamepadButtons_View : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_START)) ? GamepadButtons_Menu : 0) |
((match_state & (1<<SDL_GAMEPAD_BUTTON_LEFT_STICK)) ? GamepadButtons_LeftThumbstick : 0) |
@ -316,7 +317,7 @@ static void RAWINPUT_FillMatchState(WindowsMatchState *state, Uint64 match_state
static struct
{
XINPUT_STATE_EX state;
XINPUT_STATE state;
XINPUT_BATTERY_INFORMATION_EX battery;
SDL_bool connected; /* Currently has an active XInput device */
SDL_bool used; /* Is currently mapped to an SDL device */
@ -331,7 +332,7 @@ static void RAWINPUT_UpdateXInput()
if (xinput_device_change) {
for (user_index = 0; user_index < XUSER_MAX_COUNT; user_index++) {
XINPUT_CAPABILITIES capabilities;
xinput_state[user_index].connected = (XINPUTGETCAPABILITIES(user_index, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) ? SDL_TRUE : SDL_FALSE;
xinput_state[user_index].connected = (XINPUTGETCAPABILITIES(user_index, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS);
}
xinput_device_change = SDL_FALSE;
xinput_state_dirty = SDL_TRUE;
@ -472,7 +473,7 @@ static const IID IID_IEventHandler_Gamepad = { 0x8a7639ee, 0x624a, 0x501a, { 0xb
static HRESULT STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CGamepad *This, REFIID riid, void **ppvObject)
{
if (ppvObject == NULL) {
if (!ppvObject) {
return E_INVALIDARG;
}
@ -519,6 +520,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_InvokeRemoved(__FIEv
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4028) /* formal parameter 3 different from declaration, when using older buggy WGI headers */
#pragma warning(disable : 4113) /* X differs in parameter lists from Y, when using older buggy WGI headers */
#endif
static __FIEventHandler_1_Windows__CGaming__CInput__CGamepadVtbl gamepad_added_vtbl = {
@ -615,16 +617,18 @@ static int 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) {
return SDL_OutOfMemory();
}
WindowsGamingInputGamepadState **new_per_gamepad;
gamepad_state = SDL_calloc(1, sizeof(*gamepad_state));
if (gamepad_state == NULL) {
return SDL_OutOfMemory();
if (!gamepad_state) {
return -1;
}
new_per_gamepad = SDL_realloc(wgi_state.per_gamepad, sizeof(wgi_state.per_gamepad[0]) * (wgi_state.per_gamepad_count + 1));
if (!new_per_gamepad) {
SDL_free(gamepad_state);
return -1;
}
wgi_state.per_gamepad = new_per_gamepad;
wgi_state.per_gamepad_count++;
wgi_state.per_gamepad[wgi_state.per_gamepad_count - 1] = gamepad_state;
gamepad_state->gamepad = gamepad;
gamepad_state->connected = SDL_TRUE;
@ -839,6 +843,19 @@ static SDL_RAWINPUT_Device *RAWINPUT_DeviceFromHandle(HANDLE hDevice)
return NULL;
}
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path)
{
int slot = -1;
// The format for the raw input device path is documented here:
// https://partner.steamgames.com/doc/features/steam_controller/steam_input_gamepad_emulation_bestpractices
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
(void)SDL_sscanf(device_path, "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%*X&%*X&%*X#%d#%*u", &slot);
}
return slot;
}
static void RAWINPUT_AddDevice(HANDLE hDevice)
{
#define CHECK(expression) \
@ -850,7 +867,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
SDL_RAWINPUT_Device *curr, *last;
RID_DEVICE_INFO rdi;
UINT size;
char dev_name[MAX_PATH];
char dev_name[MAX_PATH] = { 0 };
HANDLE hFile = INVALID_HANDLE_VALUE;
/* Make sure we're not trying to add the same device twice */
@ -860,6 +877,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
/* Figure out what kind of device it is */
size = sizeof(rdi);
SDL_zero(rdi);
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICEINFO, &rdi, &size) != (UINT)-1);
CHECK(rdi.dwType == RIM_TYPEHID);
@ -880,6 +898,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
device->version = (Uint16)rdi.hid.dwVersionNumber;
device->is_xinput = SDL_TRUE;
device->is_xboxone = SDL_IsJoystickXboxOne(device->vendor_id, device->product_id);
device->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(device->vendor_id, device->product_id, dev_name);
/* Get HID Top-Level Collection Preparsed Data */
size = 0;
@ -904,6 +923,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
}
device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string);
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, manufacturer_string, product_string, 'r', 0);
if (manufacturer_string) {
SDL_free(manufacturer_string);
@ -913,14 +933,12 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
}
}
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->name, 'r', 0);
device->path = SDL_strdup(dev_name);
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
device->joystick_id = SDL_GetNextJoystickInstanceID();
device->joystick_id = SDL_GetNextObjectID();
#ifdef DEBUG_RAWINPUT
SDL_Log("Adding RAWINPUT device '%s' VID 0x%.4x, PID 0x%.4x, version %d, handle 0x%.8x\n", device->name, device->vendor_id, device->product_id, device->version, device->hDevice);
@ -991,7 +1009,8 @@ static void RAWINPUT_DetectDevices(void)
devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count);
if (devices) {
if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) {
device_count = GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST));
if (device_count != (UINT)-1) {
for (i = 0; i < device_count; ++i) {
RAWINPUT_AddDevice(devices[i].hDevice);
}
@ -1185,6 +1204,11 @@ static const char *RAWINPUT_JoystickGetDevicePath(int device_index)
return RAWINPUT_GetDeviceByIndex(device_index)->path;
}
static int RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return RAWINPUT_GetDeviceByIndex(device_index)->steam_virtual_gamepad_slot;
}
static int RAWINPUT_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -1223,8 +1247,8 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
ULONG i;
ctx = (RAWINPUT_DeviceContext *)SDL_calloc(1, sizeof(RAWINPUT_DeviceContext));
if (ctx == NULL) {
return SDL_OutOfMemory();
if (!ctx) {
return -1;
}
joystick->hwdata = ctx;
@ -1236,7 +1260,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
xinput_device_change = SDL_TRUE;
ctx->xinput_enabled = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT, SDL_TRUE);
if (ctx->xinput_enabled && (WIN_LoadXInputDLL() < 0 || XINPUTGETSTATE == NULL)) {
if (ctx->xinput_enabled && (WIN_LoadXInputDLL() < 0 || !XINPUTGETSTATE)) {
ctx->xinput_enabled = SDL_FALSE;
}
ctx->xinput_slot = XUSER_INDEX_ANY;
@ -1256,7 +1280,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
ctx->data = (HIDP_DATA *)SDL_malloc(ctx->max_data_length * sizeof(*ctx->data));
if (!ctx->data) {
RAWINPUT_JoystickClose(joystick);
return SDL_OutOfMemory();
return -1;
}
if (SDL_HidP_GetCaps(ctx->preparsed_data, &caps) != HIDP_STATUS_SUCCESS) {
@ -1301,7 +1325,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
ctx->button_indices = (USHORT *)SDL_malloc(joystick->nbuttons * sizeof(*ctx->button_indices));
if (!ctx->button_indices) {
RAWINPUT_JoystickClose(joystick);
return SDL_OutOfMemory();
return -1;
}
for (i = 0; i < caps.NumberInputButtonCaps; ++i) {
@ -1354,7 +1378,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
ctx->axis_indices = (USHORT *)SDL_malloc(joystick->naxes * sizeof(*ctx->axis_indices));
if (!ctx->axis_indices) {
RAWINPUT_JoystickClose(joystick);
return SDL_OutOfMemory();
return -1;
}
for (i = 0; i < caps.NumberInputValueCaps; ++i) {
@ -1387,7 +1411,7 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
ctx->hat_indices = (USHORT *)SDL_malloc(joystick->nhats * sizeof(*ctx->hat_indices));
if (!ctx->hat_indices) {
RAWINPUT_JoystickClose(joystick);
return SDL_OutOfMemory();
return -1;
}
for (i = 0; i < caps.NumberInputValueCaps; ++i) {
@ -1422,7 +1446,7 @@ static int RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_
if (!rumbled && ctx->xinput_correlated) {
XINPUT_VIBRATION XVibration;
if (XINPUTSETSTATE == NULL) {
if (!XINPUTSETSTATE) {
return SDL_Unsupported();
}
@ -1552,10 +1576,10 @@ static void RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
/* Map new buttons and axes into game controller controls */
static const int button_map[] = {
SDL_GAMEPAD_BUTTON_A,
SDL_GAMEPAD_BUTTON_B,
SDL_GAMEPAD_BUTTON_X,
SDL_GAMEPAD_BUTTON_Y,
SDL_GAMEPAD_BUTTON_SOUTH,
SDL_GAMEPAD_BUTTON_EAST,
SDL_GAMEPAD_BUTTON_WEST,
SDL_GAMEPAD_BUTTON_NORTH,
SDL_GAMEPAD_BUTTON_LEFT_SHOULDER,
SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER,
SDL_GAMEPAD_BUTTON_BACK,
@ -1779,7 +1803,7 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
}
}
if (!ctx->wgi_correlated) {
SDL_bool new_correlation_count = 0;
Uint8 new_correlation_count = 0;
if (RAWINPUT_MissingWindowsGamingInputSlot()) {
Uint8 correlation_id = 0;
WindowsGamingInputGamepadState *slot_idx = NULL;
@ -2194,6 +2218,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = {
RAWINPUT_JoystickDetect,
RAWINPUT_JoystickGetDeviceName,
RAWINPUT_JoystickGetDevicePath,
RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,
RAWINPUT_JoystickGetDevicePlayerIndex,
RAWINPUT_JoystickSetDevicePlayerIndex,
RAWINPUT_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -32,6 +32,7 @@
#include <cfgmgr32.h>
#include <objidlbase.h>
#include <roapi.h>
#include <initguid.h>
#ifdef ____FIReference_1_INT32_INTERFACE_DEFINED__
/* MinGW-64 uses __FIReference_1_INT32 instead of Microsoft's __FIReference_1_int */
@ -43,7 +44,7 @@
struct joystick_hwdata
{
__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller;
__x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller;
__x_ABI_CWindows_CGaming_CInput_CIGameController *game_controller;
__x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo *battery;
__x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad;
__x_ABI_CWindows_CGaming_CInput_CGamepadVibration vibration;
@ -57,14 +58,23 @@ typedef struct WindowsGamingInputControllerState
char *name;
SDL_JoystickGUID guid;
SDL_JoystickType type;
int naxes;
int nhats;
int nbuttons;
int steam_virtual_gamepad_slot;
} WindowsGamingInputControllerState;
typedef HRESULT(WINAPI *CoIncrementMTAUsage_t)(PVOID *pCookie);
typedef HRESULT(WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void **factory);
typedef HRESULT(WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING *string);
typedef HRESULT(WINAPI *WindowsDeleteString_t)(HSTRING string);
typedef PCWSTR(WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *length);
static struct
{
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics *statics;
CoIncrementMTAUsage_t CoIncrementMTAUsage;
RoGetActivationFactory_t RoGetActivationFactory;
WindowsCreateStringReference_t WindowsCreateStringReference;
WindowsDeleteString_t WindowsDeleteString;
WindowsGetStringRawBuffer_t WindowsGetStringRawBuffer;
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics *controller_statics;
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics *arcade_stick_statics;
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2 *arcade_stick_statics2;
__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics *flight_stick_statics;
@ -75,31 +85,25 @@ static struct
EventRegistrationToken controller_added_token;
EventRegistrationToken controller_removed_token;
int controller_count;
SDL_bool ro_initialized;
WindowsGamingInputControllerState *controllers;
} wgi;
static const IID IID_IRawGameControllerStatics = { 0xEB8D0792, 0xE95A, 0x4B19, { 0xAF, 0xC7, 0x0A, 0x59, 0xF8, 0xBF, 0x75, 0x9E } };
static const IID IID_IRawGameController = { 0x7CAD6D91, 0xA7E1, 0x4F71, { 0x9A, 0x78, 0x33, 0xE9, 0xC5, 0xDF, 0xEA, 0x62 } };
static const IID IID_IRawGameController2 = { 0x43C0C035, 0xBB73, 0x4756, { 0xA7, 0x87, 0x3E, 0xD6, 0xBE, 0xA6, 0x17, 0xBD } };
static const IID IID_IEventHandler_RawGameController = { 0x00621c22, 0x42e8, 0x529f, { 0x92, 0x70, 0x83, 0x6b, 0x32, 0x93, 0x1d, 0x72 } };
static const IID IID_IGameController = { 0x1BAF6522, 0x5F64, 0x42C5, { 0x82, 0x67, 0xB9, 0xFE, 0x22, 0x15, 0xBF, 0xBD } };
static const IID IID_IGameControllerBatteryInfo = { 0xDCECC681, 0x3963, 0x4DA6, { 0x95, 0x5D, 0x55, 0x3F, 0x3B, 0x6F, 0x61, 0x61 } };
static const IID IID_IArcadeStickStatics = { 0x5C37B8C8, 0x37B1, 0x4AD8, { 0x94, 0x58, 0x20, 0x0F, 0x1A, 0x30, 0x01, 0x8E } };
static const IID IID_IArcadeStickStatics2 = { 0x52B5D744, 0xBB86, 0x445A, { 0xB5, 0x9C, 0x59, 0x6F, 0x0E, 0x2A, 0x49, 0xDF } };
/*static const IID IID_IArcadeStick = { 0xB14A539D, 0xBEFB, 0x4C81, { 0x80, 0x51, 0x15, 0xEC, 0xF3, 0xB1, 0x30, 0x36 } };*/
static const IID IID_IFlightStickStatics = { 0x5514924A, 0xFECC, 0x435E, { 0x83, 0xDC, 0x5C, 0xEC, 0x8A, 0x18, 0xA5, 0x20 } };
/*static const IID IID_IFlightStick = { 0xB4A2C01C, 0xB83B, 0x4459, { 0xA1, 0xA9, 0x97, 0xB0, 0x3C, 0x33, 0xDA, 0x7C } };*/
static const IID IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
static const IID IID_IGamepadStatics2 = { 0x42676DC5, 0x0856, 0x47C4, { 0x92, 0x13, 0xB3, 0x95, 0x50, 0x4C, 0x3A, 0x3C } };
/*static const IID IID_IGamepad = { 0xBC7BB43C, 0x0A69, 0x3903, { 0x9E, 0x9D, 0xA5, 0x0F, 0x86, 0xA4, 0x5D, 0xE5 } };*/
static const IID IID_IRacingWheelStatics = { 0x3AC12CD5, 0x581B, 0x4936, { 0x9F, 0x94, 0x69, 0xF1, 0xE6, 0x51, 0x4C, 0x7D } };
static const IID IID_IRacingWheelStatics2 = { 0xE666BCAA, 0xEDFD, 0x4323, { 0xA9, 0xF6, 0x3C, 0x38, 0x40, 0x48, 0xD1, 0xED } };
/*static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };*/
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);
/* WinRT headers in official Windows SDK contain only declarations, and we have to define these GUIDs ourselves.
* https://stackoverflow.com/a/55605485/1795050
*/
DEFINE_GUID(IID___FIEventHandler_1_Windows__CGaming__CInput__CRawGameController, 0x00621c22, 0x42e8, 0x529f, 0x92, 0x70, 0x83, 0x6b, 0x32, 0x93, 0x1d, 0x72);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics, 0x5c37b8c8, 0x37b1, 0x4ad8, 0x94, 0x58, 0x20, 0x0f, 0x1a, 0x30, 0x01, 0x8e);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2, 0x52b5d744, 0xbb86, 0x445a, 0xb5, 0x9c, 0x59, 0x6f, 0x0e, 0x2a, 0x49, 0xdf);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics, 0x5514924a, 0xfecc, 0x435e, 0x83, 0xdc, 0x5c, 0xec, 0x8a, 0x18, 0xa5, 0x20);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGameController, 0x1baf6522, 0x5f64, 0x42c5, 0x82, 0x67, 0xb9, 0xfe, 0x22, 0x15, 0xbf, 0xbd);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo, 0xdcecc681, 0x3963, 0x4da6, 0x95, 0x5d, 0x55, 0x3f, 0x3b, 0x6f, 0x61, 0x61);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics, 0x8bbce529, 0xd49c, 0x39e9, 0x95, 0x60, 0xe4, 0x7d, 0xde, 0x96, 0xb7, 0xc8);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2, 0x42676dc5, 0x0856, 0x47c4, 0x92, 0x13, 0xb3, 0x95, 0x50, 0x4c, 0x3a, 0x3c);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics, 0x3ac12cd5, 0x581b, 0x4936, 0x9f, 0x94, 0x69, 0xf1, 0xe6, 0x51, 0x4c, 0x7d);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2, 0xe666bcaa, 0xedfd, 0x4323, 0xa9, 0xf6, 0x3c, 0x38, 0x40, 0x48, 0xd1, 0xed);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, 0x7cad6d91, 0xa7e1, 0x4f71, 0x9a, 0x78, 0x33, 0xe9, 0xc5, 0xdf, 0xea, 0x62);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, 0x43c0c035, 0xbb73, 0x4756, 0xa7, 0x87, 0x3e, 0xd6, 0xbe, 0xa6, 0x17, 0xbd);
DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics, 0xeb8d0792, 0xe95a, 0x4b19, 0xaf, 0xc7, 0x0a, 0x59, 0xf8, 0xbf, 0x75, 0x9e);
extern SDL_bool SDL_XINPUT_Enabled(void);
extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
@ -127,12 +131,12 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
}
raw_devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * raw_device_count);
if (raw_devices == NULL) {
SDL_OutOfMemory();
if (!raw_devices) {
return SDL_FALSE;
}
if (GetRawInputDeviceList(raw_devices, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
raw_device_count = GetRawInputDeviceList(raw_devices, &raw_device_count, sizeof(RAWINPUTDEVICELIST));
if (raw_device_count == (UINT)-1) {
SDL_free(raw_devices);
raw_devices = NULL;
return SDL_FALSE; /* oh well. */
@ -140,7 +144,7 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
for (i = 0; i < raw_device_count; i++) {
RID_DEVICE_INFO rdi;
char devName[MAX_PATH];
char devName[MAX_PATH] = { 0 };
UINT rdiSize = sizeof(rdi);
UINT nameSize = SDL_arraysize(devName);
DEVINST devNode;
@ -212,100 +216,73 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
static void WGI_LoadRawGameControllerStatics()
{
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
HRESULT hr;
HSTRING_HEADER class_name_header;
HSTRING class_name;
#ifdef __WINRT__
WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
RoGetActivationFactoryFunc = RoGetActivationFactory;
#else
{
WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
}
#endif /* __WINRT__ */
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, (void **)&wgi.statics);
if (!SUCCEEDED(hr)) {
SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%lx", hr);
}
hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_RawGameController, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_RawGameController), &class_name_header, &class_name);
if (SUCCEEDED(hr)) {
hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics, (void **)&wgi.controller_statics);
if (!SUCCEEDED(hr)) {
WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IRawGameControllerStatics", hr);
}
}
}
static void WGI_LoadOtherControllerStatics()
{
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
HRESULT hr;
HSTRING_HEADER class_name_header;
HSTRING class_name;
#ifdef __WINRT__
WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
RoGetActivationFactoryFunc = RoGetActivationFactory;
#else
{
WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
if (!wgi.arcade_stick_statics) {
hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_ArcadeStick, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_ArcadeStick), &class_name_header, &class_name);
if (SUCCEEDED(hr)) {
hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics, (void **)&wgi.arcade_stick_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID___x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2, (void **)&wgi.arcade_stick_statics2);
} else {
WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IArcadeStickStatics", hr);
}
}
}
#endif /* __WINRT__ */
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
PCWSTR pNamespace;
HSTRING_HEADER hNamespaceStringHeader;
HSTRING hNamespaceString;
pNamespace = L"Windows.Gaming.Input.ArcadeStick";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (!wgi.flight_stick_statics) {
hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_FlightStick, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_FlightStick), &class_name_header, &class_name);
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);
hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics, (void **)&wgi.flight_stick_statics);
if (!SUCCEEDED(hr)) {
SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%lx", hr);
WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IFlightStickStatics", hr);
}
}
}
pNamespace = L"Windows.Gaming.Input.Gamepad";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (!wgi.gamepad_statics) {
hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_Gamepad, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_Gamepad), &class_name_header, &class_name);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, (void **)&wgi.gamepad_statics);
hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics, (void **)&wgi.gamepad_statics);
if (SUCCEEDED(hr)) {
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, (void **)&wgi.gamepad_statics2);
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID___x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2, (void **)&wgi.gamepad_statics2);
} else {
SDL_SetError("Couldn't find IGamepadStatics: 0x%lx", hr);
WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IGamepadStatics", hr);
}
}
}
pNamespace = L"Windows.Gaming.Input.RacingWheel";
hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
if (!wgi.racing_wheel_statics) {
hr = wgi.WindowsCreateStringReference(RuntimeClass_Windows_Gaming_Input_RacingWheel, (UINT32)SDL_wcslen(RuntimeClass_Windows_Gaming_Input_RacingWheel), &class_name_header, &class_name);
if (SUCCEEDED(hr)) {
hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, (void **)&wgi.racing_wheel_statics);
hr = wgi.RoGetActivationFactory(class_name, &IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics, (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);
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID___x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2, (void **)&wgi.racing_wheel_statics2);
} else {
SDL_SetError("Couldn't find IRacingWheelStatics: 0x%lx", hr);
WIN_SetErrorFromHRESULT("Couldn't find Windows.Gaming.Input.IRacingWheelStatics", hr);
}
}
}
}
static SDL_JoystickType GetGameControllerType(__x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller)
static SDL_JoystickType GetGameControllerType(__x_ABI_CWindows_CGaming_CInput_CIGameController *game_controller)
{
__x_ABI_CWindows_CGaming_CInput_CIArcadeStick *arcade_stick = NULL;
__x_ABI_CWindows_CGaming_CInput_CIFlightStick *flight_stick = NULL;
@ -317,22 +294,22 @@ static SDL_JoystickType GetGameControllerType(__x_ABI_CWindows_CGaming_CInput_CI
*/
WGI_LoadOtherControllerStatics();
if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, gamecontroller, &gamepad)) && gamepad) {
if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, game_controller, &gamepad)) && gamepad) {
__x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(gamepad);
return SDL_JOYSTICK_TYPE_GAMEPAD;
}
if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, gamecontroller, &arcade_stick)) && arcade_stick) {
if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, game_controller, &arcade_stick)) && arcade_stick) {
__x_ABI_CWindows_CGaming_CInput_CIArcadeStick_Release(arcade_stick);
return SDL_JOYSTICK_TYPE_ARCADE_STICK;
}
if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, gamecontroller, &flight_stick)) && flight_stick) {
if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, game_controller, &flight_stick)) && flight_stick) {
__x_ABI_CWindows_CGaming_CInput_CIFlightStick_Release(flight_stick);
return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
}
if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, gamecontroller, &racing_wheel)) && racing_wheel) {
if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, game_controller, &racing_wheel)) && racing_wheel) {
__x_ABI_CWindows_CGaming_CInput_CIRacingWheel_Release(racing_wheel);
return SDL_JOYSTICK_TYPE_WHEEL;
}
@ -348,12 +325,12 @@ typedef struct RawGameControllerDelegate
static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *This, REFIID riid, void **ppvObject)
{
if (ppvObject == NULL) {
if (!ppvObject) {
return E_INVALIDARG;
}
*ppvObject = NULL;
if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID_IEventHandler_RawGameController)) {
if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID___FIEventHandler_1_Windows__CGaming__CInput__CRawGameController)) {
*ppvObject = This;
__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController_AddRef(This);
return S_OK;
@ -380,6 +357,34 @@ static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_Release(__FI
return rc;
}
static int GetSteamVirtualGamepadSlot(__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller, Uint16 vendor_id, Uint16 product_id)
{
int slot = -1;
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, (void **)&controller2);
if (SUCCEEDED(hr)) {
HSTRING hString;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_NonRoamableId(controller2, &hString);
if (SUCCEEDED(hr)) {
PCWSTR string = wgi.WindowsGetStringRawBuffer(hString, NULL);
if (string) {
char *id = WIN_StringToUTF8W(string);
if (id) {
(void)SDL_sscanf(id, "{wgi/nrid/:steam-%*X&%*X&%*X#%d#%*u}", &slot);
SDL_free(id);
}
}
wgi.WindowsDeleteString(hString);
}
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
}
return slot;
}
static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController *e)
{
HRESULT hr;
@ -393,7 +398,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
return S_OK;
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID_IRawGameController, (void **)&controller);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, (void **)&controller);
if (SUCCEEDED(hr)) {
char *name = NULL;
SDL_JoystickGUID guid = { 0 };
@ -403,42 +408,43 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
Uint16 version = 0;
SDL_JoystickType type = SDL_JOYSTICK_TYPE_UNKNOWN;
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
__x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller = NULL;
__x_ABI_CWindows_CGaming_CInput_CIGameController *game_controller = NULL;
SDL_bool ignore_joystick = SDL_FALSE;
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareVendorId(controller, &vendor);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareProductId(controller, &product);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameController, (void **)&game_controller);
if (SUCCEEDED(hr)) {
typedef PCWSTR(WINAPI * WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 * length);
typedef HRESULT(WINAPI * WindowsDeleteString_t)(HSTRING string);
boolean wireless = 0;
hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(game_controller, &wireless);
if (SUCCEEDED(hr) && wireless) {
bus = SDL_HARDWARE_BUS_BLUETOOTH;
WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = NULL;
WindowsDeleteString_t WindowsDeleteStringFunc = NULL;
#ifdef __WINRT__
WindowsGetStringRawBufferFunc = WindowsGetStringRawBuffer;
WindowsDeleteStringFunc = WindowsDeleteString;
#else
{
WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)WIN_LoadComBaseFunction("WindowsGetStringRawBuffer");
WindowsDeleteStringFunc = (WindowsDeleteString_t)WIN_LoadComBaseFunction("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);
/* Fixup for Wireless Xbox 360 Controller */
if (product == 0) {
vendor = USB_VENDOR_MICROSOFT;
product = USB_PRODUCT_XBOX360_XUSB_CONTROLLER;
}
}
__x_ABI_CWindows_CGaming_CInput_CIGameController_Release(game_controller);
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, (void **)&controller2);
if (SUCCEEDED(hr)) {
HSTRING hString;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_DisplayName(controller2, &hString);
if (SUCCEEDED(hr)) {
PCWSTR string = wgi.WindowsGetStringRawBuffer(hString, NULL);
if (string) {
name = WIN_StringToUTF8W(string);
}
wgi.WindowsDeleteString(hString);
}
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
if (name == NULL) {
if (!name) {
name = SDL_strdup("");
}
@ -463,21 +469,11 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
}
if (!ignore_joystick) {
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IGameController, (void **)&gamecontroller);
if (SUCCEEDED(hr)) {
boolean wireless;
type = GetGameControllerType(gamecontroller);
hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(gamecontroller, &wireless);
if (SUCCEEDED(hr) && wireless) {
bus = SDL_HARDWARE_BUS_BLUETOOTH;
}
__x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller);
if (game_controller) {
type = GetGameControllerType(game_controller);
}
guid = SDL_CreateJoystickGUID(bus, vendor, product, version, name, 'w', (Uint8)type);
guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, name, 'w', (Uint8)type);
if (SDL_ShouldIgnoreJoystick(name, guid)) {
ignore_joystick = SDL_TRUE;
@ -489,7 +485,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1));
if (controllers) {
WindowsGamingInputControllerState *state = &controllers[wgi.controller_count];
SDL_JoystickID joystickID = SDL_GetNextJoystickInstanceID();
SDL_JoystickID joystickID = SDL_GetNextObjectID();
SDL_zerop(state);
state->instance_id = joystickID;
@ -497,10 +493,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
state->name = name;
state->guid = guid;
state->type = type;
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(controller, &state->nbuttons);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(controller, &state->naxes);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_SwitchCount(controller, &state->nhats);
state->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(controller, vendor, product);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(controller);
@ -536,7 +529,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeRemo
return S_OK;
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID_IRawGameController, (void **)&controller);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, (void **)&controller);
if (SUCCEEDED(hr)) {
int i;
@ -609,7 +602,22 @@ static int WGI_JoystickInit(void)
if (FAILED(WIN_RoInitialize())) {
return SDL_SetError("RoInitialize() failed");
}
wgi.ro_initialized = SDL_TRUE;
#ifdef __WINRT__
wgi.CoIncrementMTAUsage = CoIncrementMTAUsage;
wgi.RoGetActivationFactory = RoGetActivationFactory;
wgi.WindowsCreateStringReference = WindowsCreateStringReference;
wgi.WindowsDeleteString = WindowsDeleteString;
wgi.WindowsGetStringRawBuffer = WindowsGetStringRawBuffer;
#else
#define RESOLVE(x) wgi.x = (x##_t)WIN_LoadComBaseFunction(#x); if (!wgi.x) return WIN_SetError("GetProcAddress failed for " #x);
RESOLVE(CoIncrementMTAUsage);
RESOLVE(RoGetActivationFactory);
RESOLVE(WindowsCreateStringReference);
RESOLVE(WindowsDeleteString);
RESOLVE(WindowsGetStringRawBuffer);
#undef RESOLVE
#endif /* __WINRT__ */
#ifndef __WINRT__
{
@ -620,15 +628,9 @@ static int WGI_JoystickInit(void)
*/
static PVOID cookie = NULL;
if (!cookie) {
typedef HRESULT(WINAPI * CoIncrementMTAUsage_t)(PVOID * pCookie);
CoIncrementMTAUsage_t CoIncrementMTAUsageFunc = (CoIncrementMTAUsage_t)WIN_LoadComBaseFunction("CoIncrementMTAUsage");
if (CoIncrementMTAUsageFunc) {
if (FAILED(CoIncrementMTAUsageFunc(&cookie))) {
return SDL_SetError("CoIncrementMTAUsage() failed");
}
} else {
/* CoIncrementMTAUsage() is present since Win8, so we should never make it here. */
return SDL_SetError("CoIncrementMTAUsage() not found");
hr = wgi.CoIncrementMTAUsage(&cookie);
if (FAILED(hr)) {
return WIN_SetErrorFromHRESULT("CoIncrementMTAUsage() failed", hr);
}
}
}
@ -636,20 +638,20 @@ static int WGI_JoystickInit(void)
WGI_LoadRawGameControllerStatics();
if (wgi.statics) {
if (wgi.controller_statics) {
__FIVectorView_1_Windows__CGaming__CInput__CRawGameController *controllers;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerAdded(wgi.statics, &controller_added.iface, &wgi.controller_added_token);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerAdded(wgi.controller_statics, &controller_added.iface, &wgi.controller_added_token);
if (!SUCCEEDED(hr)) {
SDL_SetError("add_RawGameControllerAdded() failed: 0x%lx\n", hr);
WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IRawGameControllerStatics.add_RawGameControllerAdded failed", hr);
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerRemoved(wgi.statics, &controller_removed.iface, &wgi.controller_removed_token);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_add_RawGameControllerRemoved(wgi.controller_statics, &controller_removed.iface, &wgi.controller_removed_token);
if (!SUCCEEDED(hr)) {
SDL_SetError("add_RawGameControllerRemoved() failed: 0x%lx\n", hr);
WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IRawGameControllerStatics.add_RawGameControllerRemoved failed", hr);
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_get_RawGameControllers(wgi.statics, &controllers);
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_get_RawGameControllers(wgi.controller_statics, &controllers);
if (SUCCEEDED(hr)) {
unsigned i, count = 0;
@ -692,6 +694,11 @@ static const char *WGI_JoystickGetDevicePath(int device_index)
return NULL;
}
static int WGI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return wgi.controllers[device_index].steam_virtual_gamepad_slot;
}
static int WGI_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -718,67 +725,30 @@ static int WGI_JoystickOpen(SDL_Joystick *joystick, int device_index)
boolean wireless = SDL_FALSE;
hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(*hwdata));
if (hwdata == NULL) {
return SDL_OutOfMemory();
if (!hwdata) {
return -1;
}
joystick->hwdata = hwdata;
hwdata->controller = state->controller;
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(hwdata->controller);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameController, (void **)&hwdata->gamecontroller);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID_IGameControllerBatteryInfo, (void **)&hwdata->battery);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameController, (void **)&hwdata->game_controller);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(hwdata->controller, &IID___x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo, (void **)&hwdata->battery);
if (wgi.gamepad_statics2) {
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, hwdata->gamecontroller, &hwdata->gamepad);
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, hwdata->game_controller, &hwdata->gamepad);
}
if (hwdata->gamecontroller) {
__x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(hwdata->gamecontroller, &wireless);
if (hwdata->game_controller) {
__x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(hwdata->game_controller, &wireless);
}
/* Initialize the joystick capabilities */
joystick->nbuttons = state->nbuttons;
joystick->naxes = state->naxes;
joystick->nhats = state->nhats;
joystick->epowerlevel = wireless ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(hwdata->controller, &joystick->nbuttons);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(hwdata->controller, &joystick->naxes);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_SwitchCount(hwdata->controller, &joystick->nhats);
if (wireless && hwdata->battery) {
HRESULT hr;
__x_ABI_CWindows_CDevices_CPower_CIBatteryReport *report;
hr = __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_TryGetBatteryReport(hwdata->battery, &report);
if (SUCCEEDED(hr) && report) {
int full_capacity = 0, curr_capacity = 0;
__FIReference_1_int *full_capacityP, *curr_capacityP;
hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_FullChargeCapacityInMilliwattHours(report, &full_capacityP);
if (SUCCEEDED(hr)) {
__FIReference_1_int_get_Value(full_capacityP, &full_capacity);
__FIReference_1_int_Release(full_capacityP);
}
hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_RemainingCapacityInMilliwattHours(report, &curr_capacityP);
if (SUCCEEDED(hr)) {
__FIReference_1_int_get_Value(curr_capacityP, &curr_capacity);
__FIReference_1_int_Release(curr_capacityP);
}
if (full_capacity > 0) {
float ratio = (float)curr_capacity / full_capacity;
if (ratio <= 0.05f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
} else if (ratio <= 0.20f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
} else if (ratio <= 0.70f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
} else {
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
}
}
__x_ABI_CWindows_CDevices_CPower_CIBatteryReport_Release(report);
}
}
return 0;
}
@ -789,13 +759,14 @@ static int WGI_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumbl
if (hwdata->gamepad) {
HRESULT hr;
/* Note: reusing partially filled vibration data struct */
hwdata->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
hwdata->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(hwdata->gamepad, hwdata->vibration);
if (SUCCEEDED(hr)) {
return 0;
} else {
return SDL_SetError("Setting vibration failed: 0x%lx\n", hr);
return WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IGamepad.put_Vibration failed", hr);
}
} else {
return SDL_Unsupported();
@ -809,13 +780,14 @@ static int WGI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble
if (hwdata->gamepad) {
HRESULT hr;
/* Note: reusing partially filled vibration data struct */
hwdata->vibration.LeftTrigger = (DOUBLE)left_rumble / SDL_MAX_UINT16;
hwdata->vibration.RightTrigger = (DOUBLE)right_rumble / SDL_MAX_UINT16;
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(hwdata->gamepad, hwdata->vibration);
if (SUCCEEDED(hr)) {
return 0;
} else {
return SDL_SetError("Setting vibration failed: 0x%lx\n", hr);
return WIN_SetErrorFromHRESULT("Windows.Gaming.Input.IGamepad.put_Vibration failed", hr);
}
} else {
return SDL_Unsupported();
@ -932,6 +904,43 @@ static void WGI_JoystickUpdate(SDL_Joystick *joystick)
SDL_stack_free(buttons);
SDL_stack_free(hats);
SDL_stack_free(axes);
if (joystick->epowerlevel != SDL_JOYSTICK_POWER_WIRED && hwdata->battery) {
__x_ABI_CWindows_CDevices_CPower_CIBatteryReport *report = NULL;
hr = __x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_TryGetBatteryReport(hwdata->battery, &report);
if (SUCCEEDED(hr) && report) {
int full_capacity = 0, curr_capacity = 0;
__FIReference_1_int *full_capacityP, *curr_capacityP;
hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_FullChargeCapacityInMilliwattHours(report, &full_capacityP);
if (SUCCEEDED(hr)) {
__FIReference_1_int_get_Value(full_capacityP, &full_capacity);
__FIReference_1_int_Release(full_capacityP);
}
hr = __x_ABI_CWindows_CDevices_CPower_CIBatteryReport_get_RemainingCapacityInMilliwattHours(report, &curr_capacityP);
if (SUCCEEDED(hr)) {
__FIReference_1_int_get_Value(curr_capacityP, &curr_capacity);
__FIReference_1_int_Release(curr_capacityP);
}
if (full_capacity > 0) {
float ratio = (float)curr_capacity / full_capacity;
if (ratio <= 0.05f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
} else if (ratio <= 0.20f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
} else if (ratio <= 0.70f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
} else {
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
}
}
__x_ABI_CWindows_CDevices_CPower_CIBatteryReport_Release(report);
}
}
}
static void WGI_JoystickClose(SDL_Joystick *joystick)
@ -942,8 +951,8 @@ static void WGI_JoystickClose(SDL_Joystick *joystick)
if (hwdata->controller) {
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(hwdata->controller);
}
if (hwdata->gamecontroller) {
__x_ABI_CWindows_CGaming_CInput_CIGameController_Release(hwdata->gamecontroller);
if (hwdata->game_controller) {
__x_ABI_CWindows_CGaming_CInput_CIGameController_Release(hwdata->game_controller);
}
if (hwdata->battery) {
__x_ABI_CWindows_CGaming_CInput_CIGameControllerBatteryInfo_Release(hwdata->battery);
@ -958,7 +967,7 @@ static void WGI_JoystickClose(SDL_Joystick *joystick)
static void WGI_JoystickQuit(void)
{
if (wgi.statics) {
if (wgi.controller_statics) {
while (wgi.controller_count > 0) {
IEventHandler_CRawGameControllerVtbl_InvokeRemoved(&controller_removed.iface, NULL, wgi.controllers[wgi.controller_count - 1].controller);
}
@ -988,14 +997,12 @@ static void WGI_JoystickQuit(void)
__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_Release(wgi.racing_wheel_statics2);
}
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerAdded(wgi.statics, wgi.controller_added_token);
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerRemoved(wgi.statics, wgi.controller_removed_token);
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.statics);
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerAdded(wgi.controller_statics, wgi.controller_added_token);
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerRemoved(wgi.controller_statics, wgi.controller_removed_token);
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.controller_statics);
}
if (wgi.ro_initialized) {
WIN_RoUninitialize();
}
WIN_RoUninitialize();
SDL_zero(wgi);
}
@ -1011,6 +1018,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = {
WGI_JoystickDetect,
WGI_JoystickGetDeviceName,
WGI_JoystickGetDevicePath,
WGI_JoystickGetDeviceSteamVirtualGamepadSlot,
WGI_JoystickGetDevicePlayerIndex,
WGI_JoystickSetDevicePlayerIndex,
WGI_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -176,7 +176,7 @@ static DWORD CALLBACK SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID
static void SDL_CleanupDeviceNotificationFunc(void)
{
if (cfgmgr32_lib_handle) {
if (s_DeviceNotificationFuncHandle != NULL && CM_Unregister_Notification != NULL) {
if (s_DeviceNotificationFuncHandle != NULL && CM_Unregister_Notification) {
CM_Unregister_Notification(s_DeviceNotificationFuncHandle);
s_DeviceNotificationFuncHandle = NULL;
}
@ -294,7 +294,7 @@ static int SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
}
data->messageWindow = CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
if (data->messageWindow == NULL) {
if (!data->messageWindow) {
WIN_SetError("Failed to create message window for joystick autodetect");
SDL_CleanupDeviceNotification(data);
return -1;
@ -336,7 +336,7 @@ static SDL_bool SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data,
}
}
SDL_LockMutex(mutex);
return (lastret != -1) ? SDL_TRUE : SDL_FALSE;
return (lastret != -1);
}
#endif /* !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) */
@ -377,7 +377,7 @@ static int SDLCALL SDL_JoystickThread(void *_data)
for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
XINPUT_CAPABILITIES capabilities;
const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
const SDL_bool available = (result == ERROR_SUCCESS) ? SDL_TRUE : SDL_FALSE;
const SDL_bool available = (result == ERROR_SUCCESS);
if (bOpenedXInputDevices[userId] != available) {
s_bWindowsDeviceChanged = SDL_TRUE;
bOpenedXInputDevices[userId] = available;
@ -404,18 +404,18 @@ static int SDLCALL SDL_JoystickThread(void *_data)
static int SDL_StartJoystickThread(void)
{
s_mutexJoyStickEnum = SDL_CreateMutex();
if (s_mutexJoyStickEnum == NULL) {
if (!s_mutexJoyStickEnum) {
return -1;
}
s_condJoystickThread = SDL_CreateCondition();
if (s_condJoystickThread == NULL) {
if (!s_condJoystickThread) {
return -1;
}
s_bJoystickThreadQuit = SDL_FALSE;
s_joystickThread = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
if (s_joystickThread == NULL) {
if (!s_joystickThread) {
return -1;
}
return 0;
@ -423,7 +423,7 @@ static int SDL_StartJoystickThread(void)
static void SDL_StopJoystickThread(void)
{
if (s_joystickThread == NULL) {
if (!s_joystickThread) {
return;
}
@ -453,7 +453,7 @@ static void SDL_StopJoystickThread(void)
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
{
device->send_add_event = SDL_TRUE;
device->nInstanceID = SDL_GetNextJoystickInstanceID();
device->nInstanceID = SDL_GetNextObjectID();
device->pNext = SYS_Joystick;
SYS_Joystick = device;
}
@ -612,6 +612,23 @@ static const char *WINDOWS_JoystickGetDevicePath(int device_index)
return device->path;
}
static int WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
JoyStick_DeviceData *device = SYS_Joystick;
int index;
for (index = device_index; index > 0; index--) {
device = device->pNext;
}
if (device->bXInputDevice) {
/* The slot for XInput devices can change as controllers are seated */
return SDL_XINPUT_GetSteamVirtualGamepadSlot(device->XInputUserId);
} else {
return device->steam_virtual_gamepad_slot;
}
}
static int WINDOWS_JoystickGetDevicePlayerIndex(int device_index)
{
JoyStick_DeviceData *device = SYS_Joystick;
@ -669,13 +686,10 @@ static int WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index)
}
/* allocate memory for system specific hardware data */
joystick->instance_id = device->nInstanceID;
joystick->hwdata =
(struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata));
if (joystick->hwdata == NULL) {
return SDL_OutOfMemory();
joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata));
if (!joystick->hwdata) {
return -1;
}
SDL_zerop(joystick->hwdata);
joystick->hwdata->guid = device->guid;
if (device->bXInputDevice) {
@ -794,6 +808,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = {
WINDOWS_JoystickDetect,
WINDOWS_JoystickGetDeviceName,
WINDOWS_JoystickGetDevicePath,
WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot,
WINDOWS_JoystickGetDevicePlayerIndex,
WINDOWS_JoystickSetDevicePlayerIndex,
WINDOWS_JoystickGetDeviceGUID,

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -42,6 +42,7 @@ typedef struct JoyStick_DeviceData
Uint8 XInputUserId;
DIDEVICEINSTANCE dxdevice;
char path[MAX_PATH];
int steam_virtual_gamepad_slot;
struct JoyStick_DeviceData *pNext;
} JoyStick_DeviceData;

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -38,7 +38,6 @@ extern "C" {
* Internal stuff.
*/
static SDL_bool s_bXInputEnabled = SDL_TRUE;
static char *s_arrXInputDevicePath[XUSER_MAX_COUNT];
static SDL_bool SDL_XInputUseOldJoystickMapping()
{
@ -77,156 +76,85 @@ static const char *GetXInputName(const Uint8 userid, BYTE SubType)
static char name[32];
if (SDL_XInputUseOldJoystickMapping()) {
(void)SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "X360 Controller #%d", 1 + userid);
} else {
switch (SubType) {
case XINPUT_DEVSUBTYPE_GAMEPAD:
(void)SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput Controller #%d", 1 + userid);
break;
case XINPUT_DEVSUBTYPE_WHEEL:
(void)SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput Wheel #%d", 1 + userid);
break;
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
(void)SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%d", 1 + userid);
break;
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
(void)SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput FlightStick #%d", 1 + userid);
break;
case XINPUT_DEVSUBTYPE_DANCE_PAD:
(void)SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput DancePad #%d", 1 + userid);
break;
case XINPUT_DEVSUBTYPE_GUITAR:
case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
case XINPUT_DEVSUBTYPE_GUITAR_BASS:
(void)SDL_snprintf(name, sizeof(name), "XInput Guitar #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput Guitar #%d", 1 + userid);
break;
case XINPUT_DEVSUBTYPE_DRUM_KIT:
(void)SDL_snprintf(name, sizeof(name), "XInput DrumKit #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput DrumKit #%d", 1 + userid);
break;
case XINPUT_DEVSUBTYPE_ARCADE_PAD:
(void)SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%d", 1 + userid);
break;
default:
(void)SDL_snprintf(name, sizeof(name), "XInput Device #%u", 1 + userid);
(void)SDL_snprintf(name, sizeof(name), "XInput Device #%d", 1 + userid);
break;
}
}
return name;
}
/* We can't really tell what device is being used for XInput, but we can guess
and we'll be correct for the case where only one device is connected.
*/
static void GuessXInputDevice(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 *pVersion)
static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 *pVersion)
{
#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) /* TODO: remove this ifndef __WINRT__ block, but only after integrating with UWP/WinRT's HID API */
PRAWINPUTDEVICELIST devices = NULL;
UINT i, j, device_count = 0;
XINPUT_CAPABILITIES_EX capabilities;
if ((GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!device_count)) {
return; /* oh well. */
if (!XINPUTGETCAPABILITIESEX || XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) != ERROR_SUCCESS) {
return SDL_FALSE;
}
devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count);
if (devices == NULL) {
return;
/* Fixup for Wireless Xbox 360 Controller */
if (capabilities.ProductId == 0 && capabilities.Capabilities.Flags & XINPUT_CAPS_WIRELESS) {
capabilities.VendorId = USB_VENDOR_MICROSOFT;
capabilities.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER;
}
if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
SDL_free(devices);
return; /* oh well. */
if (pVID) {
*pVID = capabilities.VendorId;
}
/* First see if we have a cached entry for this index */
if (s_arrXInputDevicePath[userid]) {
for (i = 0; i < device_count; i++) {
RID_DEVICE_INFO rdi;
char devName[128];
UINT rdiSize = sizeof(rdi);
UINT nameSize = SDL_arraysize(devName);
rdi.cbSize = sizeof(rdi);
if (devices[i].dwType == RIM_TYPEHID &&
GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 &&
GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) {
if (SDL_strcmp(devName, s_arrXInputDevicePath[userid]) == 0) {
*pVID = (Uint16)rdi.hid.dwVendorId;
*pPID = (Uint16)rdi.hid.dwProductId;
*pVersion = (Uint16)rdi.hid.dwVersionNumber;
SDL_free(devices);
return;
}
}
}
if (pPID) {
*pPID = capabilities.ProductId;
}
for (i = 0; i < device_count; i++) {
RID_DEVICE_INFO rdi;
char devName[MAX_PATH];
UINT rdiSize = sizeof(rdi);
UINT nameSize = SDL_arraysize(devName);
rdi.cbSize = sizeof(rdi);
if (devices[i].dwType == RIM_TYPEHID &&
GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != (UINT)-1 &&
GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != (UINT)-1) {
#ifdef DEBUG_JOYSTICK
SDL_Log("Raw input device: VID = 0x%x, PID = 0x%x, %s\n", rdi.hid.dwVendorId, rdi.hid.dwProductId, devName);
#endif
if (SDL_strstr(devName, "IG_") != NULL) {
SDL_bool found = SDL_FALSE;
for (j = 0; j < SDL_arraysize(s_arrXInputDevicePath); ++j) {
if (!s_arrXInputDevicePath[j]) {
continue;
}
if (SDL_strcmp(devName, s_arrXInputDevicePath[j]) == 0) {
found = SDL_TRUE;
break;
}
}
if (found) {
/* We already have this device in our XInput device list */
continue;
}
/* We don't actually know if this is the right device for this
* userid, but we'll record it so we'll at least be consistent
* when the raw device list changes.
*/
if (rdi.hid.dwVendorId == USB_VENDOR_VALVE &&
rdi.hid.dwProductId == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
/* Steam encodes the real device in the path */
int realVID = rdi.hid.dwVendorId;
int realPID = rdi.hid.dwProductId;
(void)SDL_sscanf(devName, "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%x&%x&", &realVID, &realPID);
*pVID = (Uint16)realVID;
*pPID = (Uint16)realPID;
*pVersion = 0;
} else {
*pVID = (Uint16)rdi.hid.dwVendorId;
*pPID = (Uint16)rdi.hid.dwProductId;
*pVersion = (Uint16)rdi.hid.dwVersionNumber;
}
if (s_arrXInputDevicePath[userid]) {
SDL_free(s_arrXInputDevicePath[userid]);
}
s_arrXInputDevicePath[userid] = SDL_strdup(devName);
SDL_free(devices);
return;
}
}
if (pVersion) {
*pVersion = capabilities.ProductVersion;
}
SDL_free(devices);
#endif /* !__WINRT__ */
return SDL_TRUE;
}
/* The device wasn't in the raw HID device list, it's probably Bluetooth */
*pVID = 0x045e; /* Microsoft */
*pPID = 0x02fd; /* XBox One S Bluetooth */
*pVersion = 0;
int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid)
{
XINPUT_CAPABILITIES_EX capabilities;
if (XINPUTGETCAPABILITIESEX &&
XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) == ERROR_SUCCESS &&
capabilities.VendorId == USB_VENDOR_VALVE &&
capabilities.ProductId == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
return (int)capabilities.unk2;
}
return -1;
}
static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
{
const char *name = NULL;
Uint16 vendor = 0;
Uint16 product = 0;
Uint16 version = 0;
@ -274,21 +202,21 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
}
pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData));
if (pNewJoystick == NULL) {
if (!pNewJoystick) {
return; /* better luck next time? */
}
name = GetXInputName(userid, SubType);
GetXInputDeviceInfo(userid, &vendor, &product, &version);
pNewJoystick->bXInputDevice = SDL_TRUE;
pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, GetXInputName(userid, SubType));
pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
if (!pNewJoystick->joystickname) {
SDL_free(pNewJoystick);
return; /* better luck next time? */
}
(void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%d", userid);
(void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%u", userid);
if (!SDL_XInputUseOldJoystickMapping()) {
GuessXInputDevice(userid, &vendor, &product, &version);
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 'x', SubType);
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 'x', SubType);
}
pNewJoystick->SubType = SubType;
pNewJoystick->XInputUserId = userid;
@ -300,7 +228,7 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
#ifdef SDL_JOYSTICK_HIDAPI
/* Since we're guessing about the VID/PID, use a hard-coded VID/PID to represent XInput */
if (HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER, version, pNewJoystick->joystickname)) {
if (HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, USB_PRODUCT_XBOX360_XUSB_CONTROLLER, version, pNewJoystick->joystickname)) {
/* The HIDAPI driver is taking care of this device */
SDL_free(pNewJoystick);
return;
@ -318,14 +246,6 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
WINDOWS_AddJoystickDevice(pNewJoystick);
}
static void DelXInputDevice(Uint8 userid)
{
if (s_arrXInputDevicePath[userid]) {
SDL_free(s_arrXInputDevicePath[userid]);
s_arrXInputDevicePath[userid] = NULL;
}
}
void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
{
int iuserid;
@ -339,21 +259,7 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
const Uint8 userid = (Uint8)iuserid;
XINPUT_CAPABILITIES capabilities;
if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
/* Adding a new device, must handle all removes first, or GuessXInputDevice goes terribly wrong (returns
a product/vendor ID that is not even attached to the system) when we get a remove and add on the same tick
(e.g. when disconnecting a device and the OS reassigns which userid an already-attached controller is)
*/
int iuserid2;
for (iuserid2 = iuserid - 1; iuserid2 >= 0; iuserid2--) {
const Uint8 userid2 = (Uint8)iuserid2;
XINPUT_CAPABILITIES capabilities2;
if (XINPUTGETCAPABILITIES(userid2, XINPUT_FLAG_GAMEPAD, &capabilities2) != ERROR_SUCCESS) {
DelXInputDevice(userid2);
}
}
AddXInputDevice(userid, capabilities.SubType, pContext);
} else {
DelXInputDevice(userid);
}
}
}
@ -377,7 +283,7 @@ int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystic
return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
}
SDL_zero(state);
joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS) ? SDL_TRUE : SDL_FALSE;
joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS);
joystick->hwdata->userid = userId;
/* The XInput API has a hard coded button/axis mapping, so we just match it */
@ -420,7 +326,7 @@ static void UpdateXInputJoystickBatteryInformation(SDL_Joystick *joystick, XINPU
}
}
static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
{
static WORD s_XInputButtons[] = {
XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
@ -447,7 +353,7 @@ static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE_E
UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation);
}
static void UpdateXInputJoystickState(SDL_Joystick *joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
static void UpdateXInputJoystickState(SDL_Joystick *joystick, XINPUT_STATE *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
{
static WORD s_XInputButtons[] = {
XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
@ -511,8 +417,8 @@ Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick)
void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick)
{
HRESULT result;
XINPUT_STATE_EX XInputState;
DWORD result;
XINPUT_STATE XInputState;
XINPUT_BATTERY_INFORMATION_EX XBatteryInformation;
if (!XINPUTGETSTATE) {

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -36,6 +36,7 @@ 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);
extern int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus