* Adjustment: Update libsdl to address a bug in compilation on MacOS devices.

This commit is contained in:
Robert MacGregor 2022-05-21 20:25:30 -04:00
parent 516163fd5d
commit eab544c8f3
270 changed files with 9531 additions and 3704 deletions

View file

@ -696,19 +696,20 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickG
return s_pXInputMapping;
}
#endif
if (!mapping) {
if (SDL_IsJoystickHIDAPI(guid)) {
mapping = SDL_CreateMappingForHIDAPIController(guid);
} else if (SDL_IsJoystickRAWINPUT(guid)) {
mapping = SDL_CreateMappingForRAWINPUTController(guid);
} else if (SDL_IsJoystickWGI(guid)) {
mapping = SDL_CreateMappingForWGIController(guid);
} else if (SDL_IsJoystickVirtual(guid)) {
/* We'll pick up a robust mapping in VIRTUAL_JoystickGetGamepadMapping */
#ifdef __ANDROID__
if (!mapping && !SDL_IsJoystickHIDAPI(guid)) {
mapping = SDL_CreateMappingForAndroidController(guid);
}
} else {
mapping = SDL_CreateMappingForAndroidController(guid);
#endif
if (!mapping && SDL_IsJoystickHIDAPI(guid)) {
mapping = SDL_CreateMappingForHIDAPIController(guid);
}
if (!mapping && SDL_IsJoystickRAWINPUT(guid)) {
mapping = SDL_CreateMappingForRAWINPUTController(guid);
}
if (!mapping && SDL_IsJoystickWGI(guid)) {
mapping = SDL_CreateMappingForWGIController(guid);
}
}
}
return mapping;
@ -1258,6 +1259,11 @@ static ControllerMapping_t *SDL_PrivateGenerateAutomaticControllerMapping(const
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "dpdown", &raw_map->dpdown);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "dpleft", &raw_map->dpleft);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "dpright", &raw_map->dpright);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc1", &raw_map->misc1);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "paddle1", &raw_map->paddle1);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "paddle2", &raw_map->paddle2);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "paddle3", &raw_map->paddle3);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "paddle4", &raw_map->paddle4);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "leftx", &raw_map->leftx);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "lefty", &raw_map->lefty);
SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "rightx", &raw_map->rightx);
@ -1732,6 +1738,20 @@ SDL_GameControllerNameForIndex(int device_index)
}
/*
* Get the implementation dependent path of a controller
*/
const char *
SDL_GameControllerPathForIndex(int device_index)
{
ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(device_index);
if (pSupportedController) {
return SDL_JoystickPathForIndex(device_index);
}
return NULL;
}
/**
* Get the type of a game controller.
*/
@ -2294,6 +2314,15 @@ SDL_GameControllerName(SDL_GameController *gamecontroller)
}
}
const char *
SDL_GameControllerPath(SDL_GameController *gamecontroller)
{
if (!gamecontroller)
return NULL;
return SDL_JoystickPath(SDL_GameControllerGetJoystick(gamecontroller));
}
SDL_GameControllerType
SDL_GameControllerGetType(SDL_GameController *gamecontroller)
{

View file

@ -748,8 +748,11 @@ static const char *s_ControllerMappings [] =
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,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,",
"030000005e0400008e02000073050000,Speedlink TORID Wireless 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,",
"03000000de2800000112000001000000,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,",
"03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,x:b4,y:b5,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:-a5,dpdown:+a5,dpleft:-a4,dpright:+a4,paddle1:b15,paddle2:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a7,righttrigger:a6,",
"03000000de2800000211000001000000,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,",
"03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,x:b4,y:b5,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:-a5,dpdown:+a5,dpleft:-a4,dpright:+a4,paddle1:b15,paddle2:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a7,righttrigger:a6,",
"03000000de2800004211000001000000,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,",
"03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,x:b4,y:b5,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:-a5,dpdown:+a5,dpleft:-a4,dpright:+a4,paddle1:b15,paddle2:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a7,righttrigger:a6,",
"03000000de280000fc11000001000000,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,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"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,",
@ -896,9 +899,6 @@ static const char *s_ControllerMappings [] =
"050000005e040000e0020000df070000,Xbox Wireless 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,",
"050000005e040000e0020000ff070000,Xbox Wireless 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,",
#endif
#if defined(SDL_JOYSTICK_VIRTUAL)
"00000000000000000000000000007601,Virtual Joystick,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,",
#endif
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
"default,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,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,",
#endif

View file

@ -320,6 +320,28 @@ SDL_JoystickNameForIndex(int device_index)
return name;
}
/*
* Get the implementation dependent path of a joystick
*/
const char *
SDL_JoystickPathForIndex(int device_index)
{
SDL_JoystickDriver *driver;
const char *path = NULL;
SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
path = driver->GetDevicePath(device_index);
}
SDL_UnlockJoysticks();
/* FIXME: Really we should reference count this path so it doesn't go away after unlock */
if (!path) {
SDL_Unsupported();
}
return path;
}
/*
* Get the player index of a joystick, or -1 if it's not available
*/
@ -386,6 +408,8 @@ SDL_JoystickOpen(int device_index)
SDL_Joystick *joystick;
SDL_Joystick *joysticklist;
const char *joystickname = NULL;
const char *joystickpath = NULL;
SDL_JoystickPowerLevel initial_power_level;
SDL_LockJoysticks();
@ -435,6 +459,13 @@ SDL_JoystickOpen(int device_index)
joystick->name = NULL;
}
joystickpath = driver->GetDevicePath(device_index);
if (joystickpath) {
joystick->path = SDL_strdup(joystickpath);
} else {
joystick->path = NULL;
}
joystick->guid = driver->GetDeviceGUID(device_index);
if (joystick->naxes > 0) {
@ -478,6 +509,11 @@ SDL_JoystickOpen(int device_index)
SDL_UnlockJoysticks();
/* send initial battery event */
initial_power_level = joystick->epowerlevel;
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
SDL_PrivateJoystickBatteryLevel(joystick, initial_power_level);
driver->Update(joystick);
return joystick;
@ -486,9 +522,23 @@ SDL_JoystickOpen(int device_index)
int
SDL_JoystickAttachVirtual(SDL_JoystickType type,
int naxes, int nbuttons, int nhats)
{
SDL_VirtualJoystickDesc desc;
SDL_zero(desc);
desc.version = SDL_VIRTUAL_JOYSTICK_DESC_VERSION;
desc.type = (Uint16)type;
desc.naxes = (Uint16)naxes;
desc.nbuttons = (Uint16)nbuttons;
desc.nhats = (Uint16)nhats;
return SDL_JoystickAttachVirtualEx(&desc);
}
int
SDL_JoystickAttachVirtualEx(const SDL_VirtualJoystickDesc *desc)
{
#if SDL_JOYSTICK_VIRTUAL
return SDL_JoystickAttachVirtualInner(type, naxes, nbuttons, nhats);
return SDL_JoystickAttachVirtualInner(desc);
#else
return SDL_SetError("SDL not built with virtual-joystick support");
#endif
@ -834,6 +884,23 @@ SDL_JoystickName(SDL_Joystick *joystick)
return joystick->name;
}
/*
* Get the implementation dependent path of this joystick
*/
const char *
SDL_JoystickPath(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return NULL;
}
if (!joystick->path) {
SDL_Unsupported();
return NULL;
}
return joystick->path;
}
/**
* Get the player index of an opened joystick, or -1 if it's not available
*/
@ -1006,14 +1073,13 @@ SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
SDL_LockJoysticks();
isfreshvalue = red != joystick->led_red ||
green != joystick->led_green ||
blue != joystick->led_blue;
green != joystick->led_green ||
blue != joystick->led_blue;
if ( isfreshvalue || SDL_TICKS_PASSED( SDL_GetTicks(), joystick->led_expiration ) ) {
if (isfreshvalue || SDL_TICKS_PASSED(SDL_GetTicks(), joystick->led_expiration)) {
result = joystick->driver->SetLED(joystick, red, green, blue);
joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS;
}
else {
} else {
/* Avoid spamming the driver */
result = 0;
}
@ -1100,6 +1166,7 @@ SDL_JoystickClose(SDL_Joystick *joystick)
}
SDL_free(joystick->name);
SDL_free(joystick->path);
SDL_free(joystick->serial);
/* Free the data associated with this joystick */
@ -2495,8 +2562,7 @@ SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
return SDL_TRUE;
}
if (SDL_IsGameControllerNameAndGUID(name, guid) &&
SDL_ShouldIgnoreGameController(name, guid)) {
if (SDL_ShouldIgnoreGameController(name, guid)) {
return SDL_TRUE;
}
@ -2721,7 +2787,19 @@ SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
/* update the power level for this joystick */
void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel)
{
joystick->epowerlevel = ePowerLevel;
SDL_assert(joystick->ref_count); /* make sure we are calling this only for update, not for initialisation */
if (ePowerLevel != joystick->epowerlevel) {
#if !SDL_EVENTS_DISABLED
if (SDL_GetEventState(SDL_JOYBATTERYUPDATED) == SDL_ENABLE) {
SDL_Event event;
event.type = SDL_JOYBATTERYUPDATED;
event.jbattery.which = joystick->instance_id;
event.jbattery.level = ePowerLevel;
SDL_PushEvent(&event);
}
#endif /* !SDL_EVENTS_DISABLED */
joystick->epowerlevel = ePowerLevel;
}
}
/* return its power level */

View file

@ -168,6 +168,11 @@ typedef struct _SDL_GamepadMapping
SDL_InputMapping dpdown;
SDL_InputMapping dpleft;
SDL_InputMapping dpright;
SDL_InputMapping misc1;
SDL_InputMapping paddle1;
SDL_InputMapping paddle2;
SDL_InputMapping paddle3;
SDL_InputMapping paddle4;
SDL_InputMapping leftx;
SDL_InputMapping lefty;
SDL_InputMapping rightx;

View file

@ -65,6 +65,7 @@ struct _SDL_Joystick
{
SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */
char *name; /* Joystick name - system dependent */
char *path; /* Joystick path - system dependent */
char *serial; /* Joystick serial */
SDL_JoystickGUID guid; /* Joystick guid */
@ -118,6 +119,7 @@ struct _SDL_Joystick
};
/* Device bus definitions */
#define SDL_HARDWARE_BUS_VIRTUAL 0x00
#define SDL_HARDWARE_BUS_USB 0x03
#define SDL_HARDWARE_BUS_BLUETOOTH 0x05
@ -146,6 +148,9 @@ typedef struct _SDL_JoystickDriver
/* Function to get the device-dependent name of a joystick */
const char *(*GetDeviceName)(int device_index);
/* Function to get the device-dependent path of a joystick */
const char *(*GetDevicePath)(int device_index);
/* Function to get the player index of a joystick */
int (*GetDevicePlayerIndex)(int device_index);

View file

@ -558,6 +558,12 @@ ANDROID_JoystickGetDeviceName(int device_index)
return JoystickByDevIndex(device_index)->name;
}
static const char *
ANDROID_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int
ANDROID_JoystickGetDevicePlayerIndex(int device_index)
{
@ -713,6 +719,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver =
ANDROID_JoystickGetCount,
ANDROID_JoystickDetect,
ANDROID_JoystickGetDeviceName,
ANDROID_JoystickGetDevicePath,
ANDROID_JoystickGetDevicePlayerIndex,
ANDROID_JoystickSetDevicePlayerIndex,
ANDROID_JoystickGetDeviceGUID,

View file

@ -268,9 +268,15 @@ static const char *
BSD_JoystickGetDeviceName(int device_index)
{
if (joydevnames[device_index] != NULL) {
return (joydevnames[device_index]);
return joydevnames[device_index];
}
return (joynames[device_index]);
return joynames[device_index];
}
static const char *
BSD_JoystickGetDevicePath(int device_index)
{
return joynames[device_index];
}
static int
@ -807,6 +813,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver =
BSD_JoystickGetCount,
BSD_JoystickDetect,
BSD_JoystickGetDeviceName,
BSD_JoystickGetDevicePath,
BSD_JoystickGetDevicePlayerIndex,
BSD_JoystickSetDevicePlayerIndex,
BSD_JoystickGetDeviceGUID,

0
Engine/lib/sdl/src/joystick/check_8bitdo.sh Normal file → Executable file
View file

View file

@ -744,7 +744,6 @@ DARWIN_JoystickDetect(void)
}
}
/* Function to get the device-dependent name of a joystick */
const char *
DARWIN_JoystickGetDeviceName(int device_index)
{
@ -752,6 +751,12 @@ DARWIN_JoystickGetDeviceName(int device_index)
return device ? device->product : "UNKNOWN";
}
const char *
DARWIN_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int
DARWIN_JoystickGetDevicePlayerIndex(int device_index)
{
@ -1115,6 +1120,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver =
DARWIN_JoystickGetCount,
DARWIN_JoystickDetect,
DARWIN_JoystickGetDeviceName,
DARWIN_JoystickGetDevicePath,
DARWIN_JoystickGetDevicePlayerIndex,
DARWIN_JoystickSetDevicePlayerIndex,
DARWIN_JoystickGetDeviceGUID,

View file

@ -52,6 +52,12 @@ DUMMY_JoystickGetDeviceName(int device_index)
return NULL;
}
static const char *
DUMMY_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int
DUMMY_JoystickGetDevicePlayerIndex(int device_index)
{
@ -146,6 +152,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver =
DUMMY_JoystickGetCount,
DUMMY_JoystickDetect,
DUMMY_JoystickGetDeviceName,
DUMMY_JoystickGetDevicePath,
DUMMY_JoystickGetDevicePlayerIndex,
DUMMY_JoystickSetDevicePlayerIndex,
DUMMY_JoystickGetDeviceGUID,

View file

@ -280,6 +280,12 @@ EMSCRIPTEN_JoystickGetDeviceName(int device_index)
return JoystickByDeviceIndex(device_index)->name;
}
static const char *
EMSCRIPTEN_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int
EMSCRIPTEN_JoystickGetDevicePlayerIndex(int device_index)
{
@ -444,6 +450,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver =
EMSCRIPTEN_JoystickGetCount,
EMSCRIPTEN_JoystickDetect,
EMSCRIPTEN_JoystickGetDeviceName,
EMSCRIPTEN_JoystickGetDevicePath,
EMSCRIPTEN_JoystickGetDevicePlayerIndex,
EMSCRIPTEN_JoystickSetDevicePlayerIndex,
EMSCRIPTEN_JoystickGetDeviceGUID,

View file

@ -64,15 +64,15 @@ extern "C"
char name[B_OS_NAME_LENGTH];
/* Search for attached joysticks */
nports = joystick.CountDevices();
numjoysticks = 0;
SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport));
SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname));
nports = joystick.CountDevices();
numjoysticks = 0;
SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport));
SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname));
for (i = 0; (numjoysticks < MAX_JOYSTICKS) && (i < nports); ++i)
{
if (joystick.GetDeviceName(i, name) == B_OK) {
if (joystick.Open(name) != B_ERROR) {
BString stick_name;
BString stick_name;
joystick.GetControllerName(&stick_name);
SDL_joyport[numjoysticks] = SDL_strdup(name);
SDL_joyname[numjoysticks] = SDL_CreateJoystickName(0, 0, NULL, stick_name.String());
@ -93,12 +93,16 @@ extern "C"
{
}
/* Function to get the device-dependent name of a joystick */
static const char *HAIKU_JoystickGetDeviceName(int device_index)
{
return SDL_joyname[device_index];
}
static const char *HAIKU_JoystickGetDevicePath(int device_index)
{
return SDL_joyport[device_index];
}
static int HAIKU_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -298,6 +302,7 @@ extern "C"
HAIKU_JoystickGetCount,
HAIKU_JoystickDetect,
HAIKU_JoystickGetDeviceName,
HAIKU_JoystickGetDevicePath,
HAIKU_JoystickGetDevicePlayerIndex,
HAIKU_JoystickSetDevicePlayerIndex,
HAIKU_JoystickGetDeviceGUID,

View file

@ -267,16 +267,16 @@ HIDAPI_DriverLuna_HandleBluetoothStatePacket(SDL_Joystick *joystick, SDL_DriverL
/* Battery level report */
int level = data[1] * 100 / 0xFF;
if (level == 0) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
}
else if (level <= 20) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
}
else if (level <= 70) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
}
else {
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
}
return;

View file

@ -801,18 +801,18 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev,
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
if (packet->ucBatteryLevel & 0x10) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
} else {
/* Battery level ranges from 0 to 10 */
int level = (packet->ucBatteryLevel & 0xF);
if (level == 0) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
} else if (level <= 2) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
} else if (level <= 7) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
} else {
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
}
}

View file

@ -53,7 +53,7 @@ typedef struct SDL_HIDAPI_RumbleContext
static SDL_HIDAPI_RumbleContext rumble_context;
static int SDL_HIDAPI_RumbleThread(void *data)
static int SDLCALL SDL_HIDAPI_RumbleThread(void *data)
{
SDL_HIDAPI_RumbleContext *ctx = (SDL_HIDAPI_RumbleContext *)data;

View file

@ -63,6 +63,11 @@
#define SWITCH_GYRO_SCALE 14.2842f
#define SWITCH_ACCEL_SCALE 4096.f
#define SWITCH_GYRO_SCALE_OFFSET 13371.0f
#define SWITCH_GYRO_SCALE_MULT 936.0f
#define SWITCH_ACCEL_SCALE_OFFSET 16384.0f
#define SWITCH_ACCEL_SCALE_MULT 4.0f
typedef enum {
k_eSwitchInputReportIDs_SubcommandReply = 0x21,
k_eSwitchInputReportIDs_FullControllerState = 0x30,
@ -114,6 +119,14 @@ typedef enum {
#define k_unSPIStickCalibrationEndOffset 0x604E
#define k_unSPIStickCalibrationLength (k_unSPIStickCalibrationEndOffset - k_unSPIStickCalibrationStartOffset + 1)
#define k_unSPIIMUScaleStartOffset 0x6020
#define k_unSPIIMUScaleEndOffset 0x6037
#define k_unSPIIMUScaleLength (k_unSPIIMUScaleEndOffset - k_unSPIIMUScaleStartOffset + 1)
#define k_unSPIIMUUserScaleStartOffset 0x8026
#define k_unSPIIMUUserScaleEndOffset 0x8039
#define k_unSPIIMUUserScaleLength (k_unSPIIMUUserScaleEndOffset - k_unSPIIMUUserScaleStartOffset + 1)
#pragma pack(1)
typedef struct
{
@ -266,6 +279,16 @@ typedef struct {
Sint16 sMax;
} axis[2];
} m_StickExtents[2];
struct IMUScaleData {
float fAccelScaleX;
float fAccelScaleY;
float fAccelScaleZ;
float fGyroScaleX;
float fGyroScaleY;
float fGyroScaleZ;
} m_IMUScaleData;
} SDL_DriverSwitch_Context;
@ -769,6 +792,72 @@ static SDL_bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx, Uint8 input_
return SDL_TRUE;
}
static SDL_bool LoadIMUCalibration(SDL_DriverSwitch_Context* ctx)
{
Uint8* pIMUScale;
SwitchSubcommandInputPacket_t* reply = NULL;
Sint16 sAccelRawX, sAccelRawY, sAccelRawZ, sGyroRawX, sGyroRawY, sGyroRawZ;
/* Read Calibration Info */
SwitchSPIOpData_t readParams;
readParams.unAddress = k_unSPIIMUScaleStartOffset;
readParams.ucLength = k_unSPIIMUScaleLength;
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t*)&readParams, sizeof(readParams), &reply)) {
const float accelScale = SDL_STANDARD_GRAVITY / SWITCH_ACCEL_SCALE;
const float gyroScale = (float)M_PI / 180.0f / SWITCH_GYRO_SCALE;
ctx->m_IMUScaleData.fAccelScaleX = accelScale;
ctx->m_IMUScaleData.fAccelScaleY = accelScale;
ctx->m_IMUScaleData.fAccelScaleZ = accelScale;
ctx->m_IMUScaleData.fGyroScaleX = gyroScale;
ctx->m_IMUScaleData.fGyroScaleY = gyroScale;
ctx->m_IMUScaleData.fGyroScaleZ = gyroScale;
return SDL_FALSE;
}
/* IMU scale gives us multipliers for converting raw values to real world values */
pIMUScale = reply->spiReadData.rgucReadData;
sAccelRawX = ((pIMUScale[1] << 8) & 0xF00) | pIMUScale[0];
sAccelRawY = ((pIMUScale[3] << 8) & 0xF00) | pIMUScale[2];
sAccelRawZ = ((pIMUScale[5] << 8) & 0xF00) | pIMUScale[4];
sGyroRawX = ((pIMUScale[13] << 8) & 0xF00) | pIMUScale[12];
sGyroRawY = ((pIMUScale[15] << 8) & 0xF00) | pIMUScale[14];
sGyroRawZ = ((pIMUScale[17] << 8) & 0xF00) | pIMUScale[16];
/* Check for user calibration data. If it's present and set, it'll override the factory settings */
readParams.unAddress = k_unSPIIMUUserScaleStartOffset;
readParams.ucLength = k_unSPIIMUUserScaleLength;
if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t*)&readParams, sizeof(readParams), &reply) && (pIMUScale[0] | pIMUScale[1] << 8) == 0xA1B2) {
pIMUScale = reply->spiReadData.rgucReadData;
sAccelRawX = ((pIMUScale[3] << 8) & 0xF00) | pIMUScale[2];
sAccelRawY = ((pIMUScale[5] << 8) & 0xF00) | pIMUScale[4];
sAccelRawZ = ((pIMUScale[7] << 8) & 0xF00) | pIMUScale[6];
sGyroRawX = ((pIMUScale[15] << 8) & 0xF00) | pIMUScale[14];
sGyroRawY = ((pIMUScale[17] << 8) & 0xF00) | pIMUScale[16];
sGyroRawZ = ((pIMUScale[19] << 8) & 0xF00) | pIMUScale[18];
}
/* Accelerometer scale */
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / (float)(SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / (float)(SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / (float)(SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
/* Gyro scale */
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / (float)(SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawX) * (float)M_PI / 180.0f;
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / (float)(SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawY) * (float)M_PI / 180.0f;
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / (float)(SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawZ) * (float)M_PI / 180.0f;
return SDL_TRUE;
}
static Sint16 ApplyStickCalibrationCentered(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue, Sint16 sCenter)
{
sRawValue -= sCenter;
@ -914,6 +1003,11 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
goto error;
}
if (!LoadIMUCalibration(ctx)) {
SDL_SetError("Couldn't load sensor calibration");
goto error;
}
if (!SetVibrationEnabled(ctx, 1)) {
SDL_SetError("Couldn't enable vibration");
goto error;
@ -1146,20 +1240,6 @@ HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joy
return 0;
}
static float
HIDAPI_DriverSwitch_ScaleGyro(Sint16 value)
{
float result = (value / SWITCH_GYRO_SCALE) * (float)M_PI / 180.0f;
return result;
}
static float
HIDAPI_DriverSwitch_ScaleAccel(Sint16 value)
{
float result = (value / SWITCH_ACCEL_SCALE) * SDL_STANDARD_GRAVITY;
return result;
}
static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet)
{
Sint16 axis;
@ -1357,13 +1437,13 @@ static void SendSensorUpdate(SDL_Joystick *joystick, SDL_DriverSwitch_Context *c
* users will want consistent axis mappings across devices.
*/
if (type == SDL_SENSOR_GYRO) {
data[0] = -HIDAPI_DriverSwitch_ScaleGyro(values[1]);
data[1] = HIDAPI_DriverSwitch_ScaleGyro(values[2]);
data[2] = -HIDAPI_DriverSwitch_ScaleGyro(values[0]);
data[0] = -(ctx->m_IMUScaleData.fGyroScaleY * (float)values[1]);
data[1] = ctx->m_IMUScaleData.fGyroScaleZ * (float)values[2];
data[2] = -(ctx->m_IMUScaleData.fGyroScaleX * (float)values[0]);
} else {
data[0] = -HIDAPI_DriverSwitch_ScaleAccel(values[1]);
data[1] = HIDAPI_DriverSwitch_ScaleAccel(values[2]);
data[2] = -HIDAPI_DriverSwitch_ScaleAccel(values[0]);
data[0] = -(ctx->m_IMUScaleData.fAccelScaleY * (float)values[1]);
data[1] = ctx->m_IMUScaleData.fAccelScaleZ * (float)values[2];
data[2] = -(ctx->m_IMUScaleData.fAccelScaleX * (float)values[0]);
}
/* Right Joy-Con flips some axes, so let's flip them back for consistency */
@ -1440,20 +1520,20 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
* LSB of connection nibble is USB/Switch connection status
*/
if (packet->controllerState.ucBatteryAndConnection & 0x1) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
SDL_PrivateJoystickBatteryLevel(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)
*/
int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4;
if (level == 0) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
} else if (level <= 2) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
} else if (level <= 6) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
} else {
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
}
}

View file

@ -81,13 +81,13 @@ UpdatePowerLevel(SDL_Joystick *joystick, Uint8 level)
float normalized_level = (float)level / 255.0f;
if (normalized_level <= 0.05f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
} else if (normalized_level <= 0.20f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
} else if (normalized_level <= 0.70f) {
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
} else {
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
}
}

View file

@ -134,14 +134,8 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
int i;
SDL_GameControllerType type;
SDL_JoystickGUID check_guid;
/* Make sure we have a generic GUID here, otherwise if we pass a HIDAPI
guid, this call will create a game controller mapping for the device.
*/
check_guid = device->guid;
check_guid.data[14] = 0;
if (SDL_ShouldIgnoreJoystick(device->name, check_guid)) {
if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
return NULL;
}
@ -783,6 +777,21 @@ HIDAPI_JoystickGetDeviceName(int device_index)
return name;
}
static const char *
HIDAPI_JoystickGetDevicePath(int device_index)
{
SDL_HIDAPI_Device *device;
const char *path = NULL;
device = HIDAPI_GetDeviceByIndex(device_index, NULL);
if (device) {
/* FIXME: The device could be freed after this path is returned... */
path = device->path;
}
return path;
}
static int
HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
{
@ -1030,6 +1039,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
HIDAPI_JoystickGetCount,
HIDAPI_JoystickDetect,
HIDAPI_JoystickGetDeviceName,
HIDAPI_JoystickGetDevicePath,
HIDAPI_JoystickGetDevicePlayerIndex,
HIDAPI_JoystickSetDevicePlayerIndex,
HIDAPI_JoystickGetDeviceGUID,

View file

@ -180,6 +180,10 @@ IsControllerXbox(GCController *controller)
static BOOL
IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
{
if ((@available(macOS 11.3, *)) && !GCController.shouldMonitorBackgroundEvents) {
GCController.shouldMonitorBackgroundEvents = YES;
}
Uint16 *guid16 = (Uint16 *)device->guid.data;
Uint16 vendor = 0;
Uint16 product = 0;
@ -331,11 +335,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle
}
if (SDL_strcmp(name, "Backbone One") == 0) {
/* The Backbone app uses the guide and share buttons */
if ((device->button_mask & (1 << SDL_CONTROLLER_BUTTON_GUIDE)) != 0) {
device->button_mask &= ~(1 << SDL_CONTROLLER_BUTTON_GUIDE);
--nbuttons;
}
/* The Backbone app uses share button */
if ((device->button_mask & (1 << SDL_CONTROLLER_BUTTON_MISC1)) != 0) {
device->button_mask &= ~(1 << SDL_CONTROLLER_BUTTON_MISC1);
--nbuttons;
@ -588,10 +588,6 @@ IOS_JoystickInit(void)
return 0;
}
if (@available(macOS 11.3, iOS 14.5, tvOS 14.5, *)) {
GCController.shouldMonitorBackgroundEvents = YES;
}
/* For whatever reason, this always returns an empty array on
macOS 11.0.1 */
for (GCController *controller in [GCController controllers]) {
@ -651,6 +647,12 @@ IOS_JoystickGetDeviceName(int device_index)
return device ? device->name : "Unknown";
}
static const char *
IOS_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int
IOS_JoystickGetDevicePlayerIndex(int device_index)
{
@ -739,7 +741,7 @@ IOS_JoystickOpen(SDL_Joystick *joystick, int device_index)
}
#ifdef ENABLE_MFI_SENSORS
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
GCMotion *motion = controller.motion;
if (motion && motion.hasRotationRate) {
@ -752,7 +754,7 @@ IOS_JoystickOpen(SDL_Joystick *joystick, int device_index)
#endif /* ENABLE_MFI_SENSORS */
#ifdef ENABLE_MFI_SYSTEM_GESTURE_STATE
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = joystick->hwdata->controller;
for (id key in controller.physicalInputProfile.buttons) {
GCControllerButtonInput *button = controller.physicalInputProfile.buttons[key];
@ -964,7 +966,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
}
#ifdef ENABLE_MFI_SENSORS
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCMotion *motion = controller.motion;
if (motion && motion.sensorsActive) {
float data[3];
@ -1057,7 +1059,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
}
#ifdef ENABLE_MFI_BATTERY
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCDeviceBattery *battery = controller.battery;
if (battery) {
SDL_JoystickPowerLevel ePowerLevel = SDL_JOYSTICK_POWER_UNKNOWN;
@ -1098,8 +1100,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
#ifdef ENABLE_MFI_RUMBLE
@interface SDL_RumbleMotor : NSObject
@property(nonatomic,strong) CHHapticEngine *engine API_AVAILABLE(macos(11.0), ios(13.0), tvos(14.0));
@property(nonatomic,strong) id<CHHapticPatternPlayer> player API_AVAILABLE(macos(11.0), ios(13.0), tvos(14.0));
@property(nonatomic,strong) CHHapticEngine *engine API_AVAILABLE(macos(10.16), ios(13.0), tvos(14.0));
@property(nonatomic,strong) id<CHHapticPatternPlayer> player API_AVAILABLE(macos(10.16), ios(13.0), tvos(14.0));
@property bool active;
@end
@ -1109,7 +1111,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
-(void)cleanup
{
@autoreleasepool {
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
if (self.player != nil) {
[self.player cancelAndReturnError:nil];
self.player = nil;
@ -1125,7 +1127,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
-(int)setIntensity:(float)intensity
{
@autoreleasepool {
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
NSError *error = nil;
if (self.engine == nil) {
@ -1171,7 +1173,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
}
}
-(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
-(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0))
{
@autoreleasepool {
self = [super init];
@ -1271,7 +1273,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
static SDL_RumbleContext *IOS_JoystickInitRumble(GCController *controller)
{
@autoreleasepool {
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
SDL_RumbleMotor *low_frequency_motor = [[SDL_RumbleMotor alloc] initWithController:controller locality:GCHapticsLocalityLeftHandle];
SDL_RumbleMotor *high_frequency_motor = [[SDL_RumbleMotor alloc] initWithController:controller locality:GCHapticsLocalityRightHandle];
SDL_RumbleMotor *left_trigger_motor = [[SDL_RumbleMotor alloc] initWithController:controller locality:GCHapticsLocalityLeftTrigger];
@ -1299,7 +1301,7 @@ IOS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 h
return SDL_SetError("Controller is no longer connected");
}
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
if (!device->rumble && device->controller && device->controller.haptics) {
SDL_RumbleContext *rumble = IOS_JoystickInitRumble(device->controller);
if (rumble) {
@ -1329,7 +1331,7 @@ IOS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 ri
return SDL_SetError("Controller is no longer connected");
}
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
if (!device->rumble && device->controller && device->controller.haptics) {
SDL_RumbleContext *rumble = IOS_JoystickInitRumble(device->controller);
if (rumble) {
@ -1362,7 +1364,7 @@ IOS_JoystickGetCapabilities(SDL_Joystick *joystick)
return 0;
}
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = device->controller;
#ifdef ENABLE_MFI_LIGHT
if (controller.light) {
@ -1399,7 +1401,7 @@ IOS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
return SDL_SetError("Controller is no longer connected");
}
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = device->controller;
GCDeviceLight *light = controller.light;
if (light) {
@ -1432,7 +1434,7 @@ IOS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
return SDL_SetError("Controller is no longer connected");
}
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = device->controller;
GCMotion *motion = controller.motion;
if (motion) {
@ -1495,7 +1497,7 @@ IOS_JoystickClose(SDL_Joystick *joystick)
controller.playerIndex = -1;
#ifdef ENABLE_MFI_SYSTEM_GESTURE_STATE
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
for (id key in controller.physicalInputProfile.buttons) {
GCControllerButtonInput *button = controller.physicalInputProfile.buttons[key];
if ([button isBoundToSystemGesture]) {
@ -1593,7 +1595,7 @@ SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device)
static void
GetAppleSFSymbolsNameForElement(GCControllerElement *element, char *name)
{
if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
if (element) {
[element.sfSymbolsName getCString: name maxLength: 255 encoding: NSASCIIStringEncoding];
}
@ -1627,7 +1629,7 @@ IOS_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontrol
elementName[0] = '\0';
#if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE)
if (gamecontroller && SDL_GameControllerGetJoystick(gamecontroller)->driver == &SDL_IOS_JoystickDriver) {
if (@available(iOS 14.0, tvOS 14.0, macOS 11.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = SDL_GameControllerGetJoystick(gamecontroller)->hwdata->controller;
if ([controller respondsToSelector:@selector(physicalInputProfile)]) {
NSDictionary<NSString *,GCControllerElement *> *elements = controller.physicalInputProfile.elements;
@ -1740,7 +1742,7 @@ IOS_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontrolle
elementName[0] = '\0';
#if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE)
if (gamecontroller && SDL_GameControllerGetJoystick(gamecontroller)->driver == &SDL_IOS_JoystickDriver) {
if (@available(iOS 14.0, tvOS 14.0, macOS 11.0, *)) {
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = SDL_GameControllerGetJoystick(gamecontroller)->hwdata->controller;
if ([controller respondsToSelector:@selector(physicalInputProfile)]) {
NSDictionary<NSString *,GCControllerElement *> *elements = controller.physicalInputProfile.elements;
@ -1781,6 +1783,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver =
IOS_JoystickGetCount,
IOS_JoystickDetect,
IOS_JoystickGetDeviceName,
IOS_JoystickGetDevicePath,
IOS_JoystickGetDevicePlayerIndex,
IOS_JoystickSetDevicePlayerIndex,
IOS_JoystickGetDeviceGUID,

View file

@ -82,6 +82,10 @@
#define DEBUG_INPUT_EVENTS 1
#endif
#if 0
#define DEBUG_GAMEPAD_MAPPING 1
#endif
typedef enum
{
ENUMERATION_UNSET,
@ -493,21 +497,6 @@ static void SteamControllerDisconnectedCallback(int device_instance)
}
}
#ifdef HAVE_INOTIFY
#ifdef HAVE_INOTIFY_INIT1
static int SDL_inotify_init1(void) {
return inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
}
#else
static int SDL_inotify_init1(void) {
int fd = inotify_init();
if (fd < 0) return -1;
fcntl(fd, F_SETFL, O_NONBLOCK);
fcntl(fd, F_SETFD, FD_CLOEXEC);
return fd;
}
#endif
static int
StrHasPrefix(const char *string, const char *prefix)
{
@ -562,6 +551,21 @@ IsJoystickDeviceNode(const char *node)
}
}
#ifdef HAVE_INOTIFY
#ifdef HAVE_INOTIFY_INIT1
static int SDL_inotify_init1(void) {
return inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
}
#else
static int SDL_inotify_init1(void) {
int fd = inotify_init();
if (fd < 0) return -1;
fcntl(fd, F_SETFL, O_NONBLOCK);
fcntl(fd, F_SETFD, FD_CLOEXEC);
return fd;
}
#endif
static void
LINUX_InotifyJoystickDetect(void)
{
@ -854,13 +858,18 @@ JoystickByDevIndex(int device_index)
return item;
}
/* Function to get the device-dependent name of a joystick */
static const char *
LINUX_JoystickGetDeviceName(int device_index)
{
return JoystickByDevIndex(device_index)->name;
}
static const char *
LINUX_JoystickGetDevicePath(int device_index)
{
return JoystickByDevIndex(device_index)->path;
}
static int
LINUX_JoystickGetDevicePlayerIndex(int device_index)
{
@ -921,6 +930,37 @@ allocate_balldata(SDL_Joystick *joystick)
return (0);
}
static SDL_bool
GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct input_absinfo *absinfo_y)
{
/* A "hat" is assumed to be a digital input with at most 9 possible states
* (3 per axis: negative/zero/positive), as opposed to a true "axis" which
* can report a continuous range of possible values. Unfortunately the Linux
* joystick interface makes no distinction between digital hat axes and any
* other continuous analog axis, so we have to guess. */
/* If both axes are missing, they're not anything. */
if (!absinfo_x && !absinfo_y)
return SDL_FALSE;
/* If the hint says so, treat all hats as digital. */
if (SDL_GetHintBoolean(SDL_HINT_LINUX_DIGITAL_HATS, SDL_FALSE))
return SDL_TRUE;
/* If both axes have ranges constrained between -1 and 1, they're definitely digital. */
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 || (!absinfo_x->fuzz && !absinfo_x->flat && !absinfo_x->resolution)) &&
(!absinfo_y || (!absinfo_y->fuzz && !absinfo_y->flat && !absinfo_y->resolution)))
return SDL_TRUE;
/* Otherwise, treat them as analog. */
return SDL_FALSE;
}
static void
ConfigJoystick(SDL_Joystick *joystick, int fd)
{
@ -931,6 +971,7 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
unsigned long ffbit[NBITS(FF_MAX)] = { 0 };
Uint8 key_pam_size, abs_pam_size;
SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE);
SDL_bool use_hat_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_HAT_DEADZONES, SDL_TRUE);
/* See if this device uses the new unified event API */
if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
@ -958,10 +999,45 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
++joystick->nbuttons;
}
}
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
int hat_x = -1;
int hat_y = -1;
struct input_absinfo absinfo_x;
struct input_absinfo absinfo_y;
if (test_bit(i, absbit))
hat_x = ioctl(fd, EVIOCGABS(i), &absinfo_x);
if (test_bit(i + 1, absbit))
hat_y = ioctl(fd, EVIOCGABS(i + 1), &absinfo_y);
if (GuessIfAxesAreDigitalHat((hat_x < 0 ? (void*)0 : &absinfo_x),
(hat_y < 0 ? (void*)0 : &absinfo_y))) {
const int hat_index = (i - ABS_HAT0X) / 2;
struct hat_axis_correct *correct = &joystick->hwdata->hat_correct[hat_index];
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Joystick has digital hat: #%d\n", hat_index);
if (hat_x >= 0) {
SDL_Log("X Values = { val:%d, min:%d, max:%d, fuzz:%d, flat:%d, res:%d }\n",
absinfo_x.value, absinfo_x.minimum, absinfo_x.maximum,
absinfo_x.fuzz, absinfo_x.flat, absinfo_x.resolution);
}
if (hat_y >= 0) {
SDL_Log("Y Values = { val:%d, min:%d, max:%d, fuzz:%d, flat:%d, res:%d }\n",
absinfo_y.value, absinfo_y.minimum, absinfo_y.maximum,
absinfo_y.fuzz, absinfo_y.flat, absinfo_y.resolution);
}
#endif /* DEBUG_INPUT_EVENTS */
joystick->hwdata->hats_indices[hat_index] = joystick->nhats;
joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
correct->use_deadzones = use_hat_deadzones;
correct->minimum[0] = (hat_x < 0) ? -1 : absinfo_x.minimum;
correct->maximum[0] = (hat_x < 0) ? 1 : absinfo_x.maximum;
correct->minimum[1] = (hat_y < 0) ? -1 : absinfo_y.minimum;
correct->maximum[1] = (hat_y < 0) ? 1 : absinfo_y.maximum;
++joystick->nhats;
}
}
for (i = 0; i < ABS_MAX; ++i) {
/* Skip hats */
if (i == ABS_HAT0X) {
i = ABS_HAT3Y;
/* Skip digital hats */
if (joystick->hwdata->has_hat[(i - ABS_HAT0X) / 2]) {
continue;
}
if (test_bit(i, absbit)) {
@ -973,9 +1049,9 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
}
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Joystick has absolute axis: 0x%.2x\n", i);
SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
SDL_Log("Values = { val:%d, min:%d, max:%d, fuzz:%d, flat:%d, res:%d }\n",
absinfo.value, absinfo.minimum, absinfo.maximum,
absinfo.fuzz, absinfo.flat);
absinfo.fuzz, absinfo.flat, absinfo.resolution);
#endif /* DEBUG_INPUT_EVENTS */
joystick->hwdata->abs_map[i] = joystick->naxes;
joystick->hwdata->has_abs[i] = SDL_TRUE;
@ -1003,24 +1079,6 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
++joystick->naxes;
}
}
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
struct input_absinfo absinfo;
int hat_index = (i - ABS_HAT0X) / 2;
if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
continue;
}
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Joystick has hat %d\n", hat_index);
SDL_Log("Values = { %d, %d, %d, %d, %d }\n",
absinfo.value, absinfo.minimum, absinfo.maximum,
absinfo.fuzz, absinfo.flat);
#endif /* DEBUG_INPUT_EVENTS */
joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
}
}
if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
++joystick->nballs;
}
@ -1066,14 +1124,19 @@ ConfigJoystick(SDL_Joystick *joystick, int fd)
for (i = 0; i < abs_pam_size; ++i) {
Uint8 code = joystick->hwdata->abs_pam[i];
// TODO: is there any way to detect analog hats in advance via this API?
if (code >= ABS_HAT0X && code <= ABS_HAT3Y) {
int hat_index = (code - ABS_HAT0X) / 2;
if (!joystick->hwdata->has_hat[hat_index]) {
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("Joystick has hat %d\n", hat_index);
SDL_Log("Joystick has digital hat: #%d\n", hat_index);
#endif
joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
joystick->hwdata->hat_correct[hat_index].minimum[0] = -1;
joystick->hwdata->hat_correct[hat_index].maximum[0] = 1;
joystick->hwdata->hat_correct[hat_index].minimum[1] = -1;
joystick->hwdata->hat_correct[hat_index].maximum[1] = 1;
}
} else {
#ifdef DEBUG_INPUT_EVENTS
@ -1272,26 +1335,48 @@ LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
}
static void
HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
HandleHat(SDL_Joystick *stick, int hatidx, int axis, int value)
{
const int hatnum = stick->hwdata->hats_indices[hatidx];
struct hwdata_hat *the_hat;
struct hat_axis_correct *correct;
const Uint8 position_map[3][3] = {
{SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
{SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
{SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
};
the_hat = &stick->hwdata->hats[hat];
the_hat = &stick->hwdata->hats[hatnum];
correct = &stick->hwdata->hat_correct[hatidx];
/* Hopefully we detected any analog axes and left them as is rather than trying
* to use them as digital hats, but just in case, the deadzones here will
* prevent the slightest of twitches on an analog axis from registering as a hat
* movement. If the axes really are digital, this won't hurt since they should
* only ever be sending min, 0, or max anyway. */
if (value < 0) {
value = 0;
} else if (value == 0) {
value = 1;
if (value <= correct->minimum[axis]) {
correct->minimum[axis] = value;
value = 0;
} else if (!correct->use_deadzones || value < correct->minimum[axis] / 3) {
value = 0;
} else {
value = 1;
}
} else if (value > 0) {
value = 2;
if (value >= correct->maximum[axis]) {
correct->maximum[axis] = value;
value = 2;
} else if (!correct->use_deadzones || value > correct->maximum[axis] / 3) {
value = 2;
} else {
value = 1;
}
} else { // value == 0
value = 1;
}
if (value != the_hat->axis[axis]) {
the_hat->axis[axis] = value;
SDL_PrivateJoystickHat(stick, hat,
SDL_PrivateJoystickHat(stick, hatnum,
position_map[the_hat->axis[1]][the_hat->axis[0]]);
}
}
@ -1346,10 +1431,7 @@ PollAllValues(SDL_Joystick *joystick)
/* Poll all axis */
for (i = ABS_X; i < ABS_MAX; i++) {
if (i == ABS_HAT0X) { /* we handle hats in the next loop, skip them for now. */
i = ABS_HAT3Y;
continue;
}
/* We don't need to test for digital hats here, they won't have has_abs[] set */
if (joystick->hwdata->has_abs[i]) {
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
absinfo.value = AxisCorrect(joystick, i, absinfo.value);
@ -1365,15 +1447,16 @@ PollAllValues(SDL_Joystick *joystick)
}
}
/* Poll all hats */
/* Poll all digital hats */
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++) {
const int baseaxis = i - ABS_HAT0X;
const int hatidx = baseaxis / 2;
SDL_assert(hatidx < SDL_arraysize(joystick->hwdata->has_hat));
/* We don't need to test for analog axes here, they won't have has_hat[] set */
if (joystick->hwdata->has_hat[hatidx]) {
if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
const int hataxis = baseaxis % 2;
HandleHat(joystick, joystick->hwdata->hats_indices[hatidx], hataxis, absinfo.value);
HandleHat(joystick, hatidx, hataxis, absinfo.value);
}
}
}
@ -1401,7 +1484,7 @@ static void
HandleInputEvents(SDL_Joystick *joystick)
{
struct input_event events[32];
int i, len, code;
int i, len, code, hat_index;
if (joystick->hwdata->fresh) {
PollAllValues(joystick);
@ -1436,9 +1519,11 @@ HandleInputEvents(SDL_Joystick *joystick)
case ABS_HAT2Y:
case ABS_HAT3X:
case ABS_HAT3Y:
code -= ABS_HAT0X;
HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
break;
hat_index = (code - ABS_HAT0X) / 2;
if (joystick->hwdata->has_hat[hat_index]) {
HandleHat(joystick, hat_index, code % 2, events[i].value);
break;
}
default:
events[i].value = AxisCorrect(joystick, code, events[i].value);
SDL_PrivateJoystickAxis(joystick,
@ -1491,7 +1576,7 @@ static void
HandleClassicEvents(SDL_Joystick *joystick)
{
struct js_event events[32];
int i, len, code;
int i, len, code, hat_index;
joystick->hwdata->fresh = SDL_FALSE;
while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
@ -1515,9 +1600,11 @@ HandleClassicEvents(SDL_Joystick *joystick)
case ABS_HAT2Y:
case ABS_HAT3X:
case ABS_HAT3Y:
code -= ABS_HAT0X;
HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
break;
hat_index = (code - ABS_HAT0X) / 2;
if (joystick->hwdata->has_hat[hat_index]) {
HandleHat(joystick, hat_index, code % 2, events[i].value);
break;
}
default:
SDL_PrivateJoystickAxis(joystick,
joystick->hwdata->abs_map[code],
@ -1623,10 +1710,14 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
{
SDL_Joystick *joystick;
SDL_joylist_item *item = JoystickByDevIndex(device_index);
unsigned int mapped;
if (item->checked_mapping) {
if (item->mapping) {
SDL_memcpy(out, item->mapping, sizeof(*out));
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Prior mapping for device %d", device_index);
#endif
return SDL_TRUE;
} else {
return SDL_FALSE;
@ -1674,11 +1765,17 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
if (joystick->hwdata->has_key[BTN_A]) {
out->a.kind = EMappingKind_Button;
out->a.target = joystick->hwdata->key_map[BTN_A];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped A to button %d (BTN_A)", out->a.target);
#endif
}
if (joystick->hwdata->has_key[BTN_B]) {
out->b.kind = EMappingKind_Button;
out->b.target = joystick->hwdata->key_map[BTN_B];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped B to button %d (BTN_B)", out->b.target);
#endif
}
/* Xbox controllers use BTN_X and BTN_Y, and PS4 controllers use BTN_WEST and BTN_NORTH */
@ -1686,47 +1783,74 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
if (joystick->hwdata->has_key[BTN_WEST]) {
out->x.kind = EMappingKind_Button;
out->x.target = joystick->hwdata->key_map[BTN_WEST];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped X to button %d (BTN_WEST)", out->x.target);
#endif
}
if (joystick->hwdata->has_key[BTN_NORTH]) {
out->y.kind = EMappingKind_Button;
out->y.target = joystick->hwdata->key_map[BTN_NORTH];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped Y to button %d (BTN_NORTH)", out->y.target);
#endif
}
} else {
if (joystick->hwdata->has_key[BTN_X]) {
out->x.kind = EMappingKind_Button;
out->x.target = joystick->hwdata->key_map[BTN_X];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped X to button %d (BTN_X)", out->x.target);
#endif
}
if (joystick->hwdata->has_key[BTN_Y]) {
out->y.kind = EMappingKind_Button;
out->y.target = joystick->hwdata->key_map[BTN_Y];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped Y to button %d (BTN_Y)", out->y.target);
#endif
}
}
if (joystick->hwdata->has_key[BTN_SELECT]) {
out->back.kind = EMappingKind_Button;
out->back.target = joystick->hwdata->key_map[BTN_SELECT];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped BACK to button %d (BTN_SELECT)", out->back.target);
#endif
}
if (joystick->hwdata->has_key[BTN_START]) {
out->start.kind = EMappingKind_Button;
out->start.target = joystick->hwdata->key_map[BTN_START];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped START to button %d (BTN_START)", out->start.target);
#endif
}
if (joystick->hwdata->has_key[BTN_THUMBL]) {
out->leftstick.kind = EMappingKind_Button;
out->leftstick.target = joystick->hwdata->key_map[BTN_THUMBL];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFTSTICK to button %d (BTN_THUMBL)", out->leftstick.target);
#endif
}
if (joystick->hwdata->has_key[BTN_THUMBR]) {
out->rightstick.kind = EMappingKind_Button;
out->rightstick.target = joystick->hwdata->key_map[BTN_THUMBR];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped RIGHTSTICK to button %d (BTN_THUMBR)", out->rightstick.target);
#endif
}
if (joystick->hwdata->has_key[BTN_MODE]) {
out->guide.kind = EMappingKind_Button;
out->guide.target = joystick->hwdata->key_map[BTN_MODE];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped GUIDE to button %d (BTN_MODE)", out->guide.target);
#endif
}
/*
@ -1734,84 +1858,191 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
can be digital, or analog, or both at the same time.
*/
/* Prefer digital shoulder buttons, but settle for analog if missing. */
/* Prefer digital shoulder buttons, but settle for digital or analog hat. */
mapped = 0;
if (joystick->hwdata->has_key[BTN_TL]) {
out->leftshoulder.kind = EMappingKind_Button;
out->leftshoulder.target = joystick->hwdata->key_map[BTN_TL];
mapped |= 0x1;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFTSHOULDER to button %d (BTN_TL)", out->leftshoulder.target);
#endif
}
if (joystick->hwdata->has_key[BTN_TR]) {
out->rightshoulder.kind = EMappingKind_Button;
out->rightshoulder.target = joystick->hwdata->key_map[BTN_TR];
mapped |= 0x2;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped RIGHTSHOULDER to button %d (BTN_TR)", out->rightshoulder.target);
#endif
}
if (joystick->hwdata->has_hat[1] && /* Check if ABS_HAT1{X, Y} is available. */
(!joystick->hwdata->has_key[BTN_TL] || !joystick->hwdata->has_key[BTN_TR])) {
if (mapped != 0x3 && joystick->hwdata->has_hat[1]) {
int hat = joystick->hwdata->hats_indices[1] << 4;
out->leftshoulder.kind = EMappingKind_Hat;
out->rightshoulder.kind = EMappingKind_Hat;
out->leftshoulder.target = hat | 0x4;
out->rightshoulder.target = hat | 0x2;
mapped |= 0x3;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFT+RIGHTSHOULDER to hat 1 (ABS_HAT1X, ABS_HAT1Y)");
#endif
}
/* Prefer analog triggers, but settle for digital if missing. */
if (joystick->hwdata->has_hat[2]) { /* Check if ABS_HAT2{X,Y} is available. */
if (!(mapped & 0x1) && joystick->hwdata->has_abs[ABS_HAT1Y]) {
out->leftshoulder.kind = EMappingKind_Axis;
out->leftshoulder.target = joystick->hwdata->abs_map[ABS_HAT1Y];
mapped |= 0x1;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFTSHOULDER to axis %d (ABS_HAT1Y)", out->leftshoulder.target);
#endif
}
if (!(mapped & 0x2) && joystick->hwdata->has_abs[ABS_HAT1X]) {
out->rightshoulder.kind = EMappingKind_Axis;
out->rightshoulder.target = joystick->hwdata->abs_map[ABS_HAT1X];
mapped |= 0x2;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped RIGHTSHOULDER to axis %d (ABS_HAT1X)", out->rightshoulder.target);
#endif
}
/* Prefer analog triggers, but settle for digital hat or buttons. */
mapped = 0;
if (joystick->hwdata->has_abs[ABS_HAT2Y]) {
out->lefttrigger.kind = EMappingKind_Axis;
out->lefttrigger.target = joystick->hwdata->abs_map[ABS_HAT2Y];
mapped |= 0x1;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFTTRIGGER to axis %d (ABS_HAT2Y)", out->lefttrigger.target);
#endif
} else if (joystick->hwdata->has_abs[ABS_Z]) {
out->lefttrigger.kind = EMappingKind_Axis;
out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z];
mapped |= 0x1;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFTTRIGGER to axis %d (ABS_Z)", out->lefttrigger.target);
#endif
}
if (joystick->hwdata->has_abs[ABS_HAT2X]) {
out->righttrigger.kind = EMappingKind_Axis;
out->righttrigger.target = joystick->hwdata->abs_map[ABS_HAT2X];
mapped |= 0x2;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped RIGHTTRIGGER to axis %d (ABS_HAT2X)", out->righttrigger.target);
#endif
} else if (joystick->hwdata->has_abs[ABS_RZ]) {
out->righttrigger.kind = EMappingKind_Axis;
out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ];
mapped |= 0x2;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped RIGHTTRIGGER to axis %d (ABS_RZ)", out->righttrigger.target);
#endif
}
if (mapped != 0x3 && joystick->hwdata->has_hat[2]) {
int hat = joystick->hwdata->hats_indices[2] << 4;
out->lefttrigger.kind = EMappingKind_Hat;
out->righttrigger.kind = EMappingKind_Hat;
out->lefttrigger.target = hat | 0x4;
out->righttrigger.target = hat | 0x2;
} else {
if (joystick->hwdata->has_abs[ABS_Z]) {
out->lefttrigger.kind = EMappingKind_Axis;
out->lefttrigger.target = joystick->hwdata->abs_map[ABS_Z];
} else if (joystick->hwdata->has_key[BTN_TL2]) {
out->lefttrigger.kind = EMappingKind_Button;
out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
}
if (joystick->hwdata->has_abs[ABS_RZ]) {
out->righttrigger.kind = EMappingKind_Axis;
out->righttrigger.target = joystick->hwdata->abs_map[ABS_RZ];
} else if (joystick->hwdata->has_key[BTN_TR2]) {
out->righttrigger.kind = EMappingKind_Button;
out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
}
mapped |= 0x3;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFT+RIGHTTRIGGER to hat 2 (ABS_HAT2X, ABS_HAT2Y)");
#endif
}
/* Prefer digital D-Pad, but settle for analog if missing. */
if (!(mapped & 0x1) && joystick->hwdata->has_key[BTN_TL2]) {
out->lefttrigger.kind = EMappingKind_Button;
out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
mapped |= 0x1;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFTTRIGGER to button %d (BTN_TL2)", out->lefttrigger.target);
#endif
}
if (!(mapped & 0x2) && joystick->hwdata->has_key[BTN_TR2]) {
out->righttrigger.kind = EMappingKind_Button;
out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
mapped |= 0x2;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped RIGHTTRIGGER to button %d (BTN_TR2)", out->righttrigger.target);
#endif
}
/* Prefer digital D-Pad buttons, but settle for digital or analog hat. */
mapped = 0;
if (joystick->hwdata->has_key[BTN_DPAD_UP]) {
out->dpup.kind = EMappingKind_Button;
out->dpup.target = joystick->hwdata->key_map[BTN_DPAD_UP];
mapped |= 0x1;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped DPUP to button %d (BTN_DPAD_UP)", out->dpup.target);
#endif
}
if (joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
out->dpdown.kind = EMappingKind_Button;
out->dpdown.target = joystick->hwdata->key_map[BTN_DPAD_DOWN];
mapped |= 0x2;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped DPDOWN to button %d (BTN_DPAD_DOWN)", out->dpdown.target);
#endif
}
if (joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
out->dpleft.kind = EMappingKind_Button;
out->dpleft.target = joystick->hwdata->key_map[BTN_DPAD_LEFT];
mapped |= 0x4;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped DPLEFT to button %d (BTN_DPAD_LEFT)", out->dpleft.target);
#endif
}
if (joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
out->dpright.kind = EMappingKind_Button;
out->dpright.target = joystick->hwdata->key_map[BTN_DPAD_RIGHT];
mapped |= 0x8;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped DPRIGHT to button %d (BTN_DPAD_RIGHT)", out->dpright.target);
#endif
}
if (joystick->hwdata->has_hat[0] && /* Check if ABS_HAT0{X,Y} is available. */
(!joystick->hwdata->has_key[BTN_DPAD_LEFT] || !joystick->hwdata->has_key[BTN_DPAD_RIGHT] ||
!joystick->hwdata->has_key[BTN_DPAD_UP] || !joystick->hwdata->has_key[BTN_DPAD_DOWN])) {
int hat = joystick->hwdata->hats_indices[0] << 4;
out->dpleft.kind = EMappingKind_Hat;
out->dpright.kind = EMappingKind_Hat;
out->dpup.kind = EMappingKind_Hat;
out->dpdown.kind = EMappingKind_Hat;
out->dpleft.target = hat | 0x8;
out->dpright.target = hat | 0x2;
out->dpup.target = hat | 0x1;
out->dpdown.target = hat | 0x4;
if (mapped != 0xF) {
if (joystick->hwdata->has_hat[0]) {
int hat = joystick->hwdata->hats_indices[0] << 4;
out->dpleft.kind = EMappingKind_Hat;
out->dpright.kind = EMappingKind_Hat;
out->dpup.kind = EMappingKind_Hat;
out->dpdown.kind = EMappingKind_Hat;
out->dpleft.target = hat | 0x8;
out->dpright.target = hat | 0x2;
out->dpup.target = hat | 0x1;
out->dpdown.target = hat | 0x4;
mapped |= 0xF;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped DPUP+DOWN+LEFT+RIGHT to hat 0 (ABS_HAT0X, ABS_HAT0Y)");
#endif
} else if (joystick->hwdata->has_abs[ABS_HAT0X] && joystick->hwdata->has_abs[ABS_HAT0Y]) {
out->dpleft.kind = EMappingKind_Axis;
out->dpright.kind = EMappingKind_Axis;
out->dpup.kind = EMappingKind_Axis;
out->dpdown.kind = EMappingKind_Axis;
out->dpleft.target = joystick->hwdata->abs_map[ABS_HAT0X];
out->dpright.target = joystick->hwdata->abs_map[ABS_HAT0X];
out->dpup.target = joystick->hwdata->abs_map[ABS_HAT0Y];
out->dpdown.target = joystick->hwdata->abs_map[ABS_HAT0Y];
mapped |= 0xF;
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped DPUP+DOWN to axis %d (ABS_HAT0Y)", out->dpup.target);
SDL_Log("Mapped DPLEFT+RIGHT to axis %d (ABS_HAT0X)", out->dpleft.target);
#endif
}
}
if (joystick->hwdata->has_abs[ABS_X] && joystick->hwdata->has_abs[ABS_Y]) {
@ -1819,6 +2050,10 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
out->lefty.kind = EMappingKind_Axis;
out->leftx.target = joystick->hwdata->abs_map[ABS_X];
out->lefty.target = joystick->hwdata->abs_map[ABS_Y];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped LEFTX to axis %d (ABS_X)", out->leftx.target);
SDL_Log("Mapped LEFTY to axis %d (ABS_Y)", out->lefty.target);
#endif
}
if (joystick->hwdata->has_abs[ABS_RX] && joystick->hwdata->has_abs[ABS_RY]) {
@ -1826,6 +2061,10 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
out->righty.kind = EMappingKind_Axis;
out->rightx.target = joystick->hwdata->abs_map[ABS_RX];
out->righty.target = joystick->hwdata->abs_map[ABS_RY];
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Mapped RIGHTX to axis %d (ABS_RX)", out->rightx.target);
SDL_Log("Mapped RIGHTY to axis %d (ABS_RY)", out->righty.target);
#endif
}
LINUX_JoystickClose(joystick);
@ -1836,6 +2075,9 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
if (item->mapping) {
SDL_memcpy(item->mapping, out, sizeof(*out));
}
#ifdef DEBUG_GAMEPAD_MAPPING
SDL_Log("Generated mapping for device %d", device_index);
#endif
return SDL_TRUE;
}
@ -1846,6 +2088,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver =
LINUX_JoystickGetCount,
LINUX_JoystickDetect,
LINUX_JoystickGetDeviceName,
LINUX_JoystickGetDevicePath,
LINUX_JoystickGetDevicePlayerIndex,
LINUX_JoystickSetDevicePlayerIndex,
LINUX_JoystickGetDeviceGUID,

View file

@ -83,6 +83,12 @@ struct joystick_hwdata
/* 4 = (ABS_HAT3X-ABS_HAT0X)/2 (see input-event-codes.h in kernel) */
int hats_indices[4];
SDL_bool has_hat[4];
struct hat_axis_correct
{
SDL_bool use_deadzones;
int minimum[2];
int maximum[2];
} hat_correct[4];
/* Set when gamepad is pending removal due to ENODEV read error */
SDL_bool gone;

View file

@ -377,15 +377,17 @@ static void OS2_JoystickDetect(void)
{
}
/***********************************************************/
/* Function to get the device-dependent name of a joystick */
/***********************************************************/
static const char *OS2_JoystickGetDeviceName(int device_index)
{
/* No need to verify if device exists, already done in upper layer */
return SYS_JoyData[device_index].szDeviceName;
}
static const char *OS2_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int OS2_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -779,6 +781,7 @@ SDL_JoystickDriver SDL_OS2_JoystickDriver =
OS2_NumJoysticks,
OS2_JoystickDetect,
OS2_JoystickGetDeviceName,
OS2_JoystickGetDevicePath,
OS2_JoystickGetDevicePlayerIndex,
OS2_JoystickSetDevicePlayerIndex,
OS2_JoystickGetDeviceGUID,

View file

@ -142,7 +142,6 @@ static void PSP_JoystickDetect(void)
}
#if 0
/* Function to get the device-dependent name of a joystick */
static const char *PSP_JoystickName(int idx)
{
if (idx == 0) return "PSP controller";
@ -151,12 +150,16 @@ static const char *PSP_JoystickName(int idx)
}
#endif
/* Function to get the device-dependent name of a joystick */
static const char *PSP_JoystickGetDeviceName(int device_index)
{
return "PSP builtin joypad";
}
static const char *PSP_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int PSP_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -304,6 +307,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver =
PSP_NumJoysticks,
PSP_JoystickDetect,
PSP_JoystickGetDeviceName,
PSP_JoystickGetDevicePath,
PSP_JoystickGetDevicePlayerIndex,
PSP_JoystickSetDevicePlayerIndex,
PSP_JoystickGetDeviceGUID,

View file

@ -24,11 +24,11 @@
/* This is the virtual implementation of the SDL joystick API */
#include "SDL_endian.h"
#include "SDL_virtualjoystick_c.h"
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;
static joystick_hwdata * g_VJoys = NULL;
@ -56,18 +56,6 @@ VIRTUAL_FreeHWData(joystick_hwdata *hwdata)
if (!hwdata) {
return;
}
if (hwdata->axes) {
SDL_free((void *)hwdata->axes);
hwdata->axes = NULL;
}
if (hwdata->buttons) {
SDL_free((void *)hwdata->buttons);
hwdata->buttons = NULL;
}
if (hwdata->hats) {
SDL_free(hwdata->hats);
hwdata->hats = NULL;
}
/* Remove hwdata from SDL-global list */
while (cur) {
@ -83,51 +71,170 @@ VIRTUAL_FreeHWData(joystick_hwdata *hwdata)
cur = cur->next;
}
if (hwdata->joystick) {
hwdata->joystick->hwdata = NULL;
hwdata->joystick = NULL;
}
if (hwdata->name) {
SDL_free(hwdata->name);
hwdata->name = NULL;
}
if (hwdata->axes) {
SDL_free((void *)hwdata->axes);
hwdata->axes = NULL;
}
if (hwdata->buttons) {
SDL_free((void *)hwdata->buttons);
hwdata->buttons = NULL;
}
if (hwdata->hats) {
SDL_free(hwdata->hats);
hwdata->hats = NULL;
}
SDL_free(hwdata);
}
int
SDL_JoystickAttachVirtualInner(SDL_JoystickType type,
int naxes,
int nbuttons,
int nhats)
SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc)
{
joystick_hwdata *hwdata = NULL;
int device_index = -1;
const char *name = NULL;
Uint16 *guid16;
int axis_triggerleft = -1;
int axis_triggerright = -1;
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);
}
hwdata = SDL_calloc(1, sizeof(joystick_hwdata));
if (!hwdata) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
}
SDL_memcpy(&hwdata->desc, desc, sizeof(*desc));
hwdata->naxes = naxes;
hwdata->nbuttons = nbuttons;
hwdata->nhats = nhats;
hwdata->name = "Virtual Joystick";
if (hwdata->desc.name) {
name = hwdata->desc.name;
} else {
switch (hwdata->desc.type) {
case SDL_JOYSTICK_TYPE_GAMECONTROLLER:
name = "Virtual Controller";
break;
case SDL_JOYSTICK_TYPE_WHEEL:
name = "Virtual Wheel";
break;
case SDL_JOYSTICK_TYPE_ARCADE_STICK:
name = "Virtual Arcade Stick";
break;
case SDL_JOYSTICK_TYPE_FLIGHT_STICK:
name = "Virtual Flight Stick";
break;
case SDL_JOYSTICK_TYPE_DANCE_PAD:
name = "Virtual Dance Pad";
break;
case SDL_JOYSTICK_TYPE_GUITAR:
name = "Virtual Guitar";
break;
case SDL_JOYSTICK_TYPE_DRUM_KIT:
name = "Virtual Drum Kit";
break;
case SDL_JOYSTICK_TYPE_ARCADE_PAD:
name = "Virtual Arcade Pad";
break;
case SDL_JOYSTICK_TYPE_THROTTLE:
name = "Virtual Throttle";
break;
default:
name = "Virtual Joystick";
break;
}
}
hwdata->name = SDL_strdup(name);
if (hwdata->desc.type == SDL_JOYSTICK_TYPE_GAMECONTROLLER) {
int i, axis;
if (hwdata->desc.button_mask == 0) {
for (i = 0; i < hwdata->desc.nbuttons && i < sizeof(hwdata->desc.button_mask)*8; ++i) {
hwdata->desc.button_mask |= (1 << i);
}
}
if (hwdata->desc.axis_mask == 0) {
if (hwdata->desc.naxes >= 2) {
hwdata->desc.axis_mask |= ((1 << SDL_CONTROLLER_AXIS_LEFTX) | (1 << SDL_CONTROLLER_AXIS_LEFTY));
}
if (hwdata->desc.naxes >= 4) {
hwdata->desc.axis_mask |= ((1 << SDL_CONTROLLER_AXIS_RIGHTX) | (1 << SDL_CONTROLLER_AXIS_RIGHTY));
}
if (hwdata->desc.naxes >= 6) {
hwdata->desc.axis_mask |= ((1 << SDL_CONTROLLER_AXIS_TRIGGERLEFT) | (1 << SDL_CONTROLLER_AXIS_TRIGGERRIGHT));
}
}
/* Find the trigger axes */
axis = 0;
for (i = 0; axis < hwdata->desc.naxes && i < SDL_CONTROLLER_AXIS_MAX; ++i) {
if (hwdata->desc.axis_mask & (1 << i)) {
if (i == SDL_CONTROLLER_AXIS_TRIGGERLEFT) {
axis_triggerleft = axis;
}
if (i == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) {
axis_triggerright = axis;
}
++axis;
}
}
}
/* We only need 16 bits for each of these; space them out to fill 128. */
/* Byteswap so devices get same GUID on little/big endian platforms. */
guid16 = (Uint16 *)hwdata->guid.data;
*guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_VIRTUAL);
*guid16++ = 0;
*guid16++ = SDL_SwapLE16(hwdata->desc.vendor_id);
*guid16++ = 0;
*guid16++ = SDL_SwapLE16(hwdata->desc.product_id);
*guid16++ = 0;
*guid16++ = 0;
*guid16++ = 0; /* This will be overwritten below with the virtual controller signature */
/* Note that this is a Virtual device and what subtype it is */
hwdata->guid.data[14] = 'v';
hwdata->guid.data[15] = (Uint8)type;
hwdata->guid.data[15] = (Uint8)hwdata->desc.type;
/* Allocate fields for different control-types */
if (naxes > 0) {
hwdata->axes = SDL_calloc(naxes, sizeof(Sint16));
if (hwdata->desc.naxes > 0) {
hwdata->axes = SDL_calloc(hwdata->desc.naxes, sizeof(Sint16));
if (!hwdata->axes) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
}
/* Trigger axes are at minimum value at rest */
if (axis_triggerleft >= 0) {
hwdata->axes[axis_triggerleft] = SDL_JOYSTICK_AXIS_MIN;
}
if (axis_triggerright >= 0) {
hwdata->axes[axis_triggerright] = SDL_JOYSTICK_AXIS_MIN;
}
}
if (nbuttons > 0) {
hwdata->buttons = SDL_calloc(nbuttons, sizeof(Uint8));
if (hwdata->desc.nbuttons > 0) {
hwdata->buttons = SDL_calloc(hwdata->desc.nbuttons, sizeof(Uint8));
if (!hwdata->buttons) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
}
}
if (nhats > 0) {
hwdata->hats = SDL_calloc(nhats, sizeof(Uint8));
if (hwdata->desc.nhats > 0) {
hwdata->hats = SDL_calloc(hwdata->desc.nhats, sizeof(Uint8));
if (!hwdata->hats) {
VIRTUAL_FreeHWData(hwdata);
return SDL_OutOfMemory();
@ -138,8 +245,16 @@ SDL_JoystickAttachVirtualInner(SDL_JoystickType type,
hwdata->instance_id = SDL_GetNextJoystickInstanceID();
/* Add virtual joystick to SDL-global lists */
hwdata->next = g_VJoys;
g_VJoys = hwdata;
if (g_VJoys) {
joystick_hwdata *last;
for (last = g_VJoys; last->next; last = last->next) {
continue;
}
last->next = hwdata;
} else {
g_VJoys = hwdata;
}
SDL_PrivateJoystickAdded(hwdata->instance_id);
/* Return the new virtual-device's index */
@ -176,7 +291,7 @@ SDL_JoystickSetVirtualAxisInner(SDL_Joystick *joystick, int axis, Sint16 value)
}
hwdata = (joystick_hwdata *)joystick->hwdata;
if (axis < 0 || axis >= hwdata->naxes) {
if (axis < 0 || axis >= hwdata->desc.naxes) {
SDL_UnlockJoysticks();
return SDL_SetError("Invalid axis index");
}
@ -201,7 +316,7 @@ SDL_JoystickSetVirtualButtonInner(SDL_Joystick *joystick, int button, Uint8 valu
}
hwdata = (joystick_hwdata *)joystick->hwdata;
if (button < 0 || button >= hwdata->nbuttons) {
if (button < 0 || button >= hwdata->desc.nbuttons) {
SDL_UnlockJoysticks();
return SDL_SetError("Invalid button index");
}
@ -226,7 +341,7 @@ SDL_JoystickSetVirtualHatInner(SDL_Joystick *joystick, int hat, Uint8 value)
}
hwdata = (joystick_hwdata *)joystick->hwdata;
if (hat < 0 || hat >= hwdata->nhats) {
if (hat < 0 || hat >= hwdata->desc.nhats) {
SDL_UnlockJoysticks();
return SDL_SetError("Invalid hat index");
}
@ -271,7 +386,14 @@ VIRTUAL_JoystickGetDeviceName(int device_index)
if (!hwdata) {
return NULL;
}
return hwdata->name ? hwdata->name : "";
return hwdata->name;
}
static const char *
VIRTUAL_JoystickGetDevicePath(int device_index)
{
return NULL;
}
@ -285,6 +407,11 @@ VIRTUAL_JoystickGetDevicePlayerIndex(int device_index)
static void
VIRTUAL_JoystickSetDevicePlayerIndex(int device_index, int player_index)
{
joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
if (hwdata && hwdata->desc.SetPlayerIndex) {
hwdata->desc.SetPlayerIndex(hwdata->desc.userdata, player_index);
}
}
@ -319,15 +446,12 @@ VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index)
if (!hwdata) {
return SDL_SetError("No such device");
}
if (hwdata->opened) {
return SDL_SetError("Joystick already opened");
}
joystick->instance_id = hwdata->instance_id;
joystick->hwdata = hwdata;
joystick->naxes = hwdata->naxes;
joystick->nbuttons = hwdata->nbuttons;
joystick->nhats = hwdata->nhats;
hwdata->opened = SDL_TRUE;
joystick->naxes = hwdata->desc.naxes;
joystick->nbuttons = hwdata->desc.nbuttons;
joystick->nhats = hwdata->desc.nhats;
hwdata->joystick = joystick;
return 0;
}
@ -335,33 +459,99 @@ VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index)
static int
VIRTUAL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
return SDL_Unsupported();
int result;
if (joystick->hwdata) {
joystick_hwdata *hwdata = joystick->hwdata;
if (hwdata->desc.Rumble) {
result = hwdata->desc.Rumble(hwdata->desc.userdata, low_frequency_rumble, high_frequency_rumble);
} else {
result = SDL_Unsupported();
}
} else {
result = SDL_SetError("Rumble failed, device disconnected");
}
return result;
}
static int
VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{
return SDL_Unsupported();
int result;
if (joystick->hwdata) {
joystick_hwdata *hwdata = joystick->hwdata;
if (hwdata->desc.RumbleTriggers) {
result = hwdata->desc.RumbleTriggers(hwdata->desc.userdata, left_rumble, right_rumble);
} else {
result = SDL_Unsupported();
}
} else {
result = SDL_SetError("Rumble failed, device disconnected");
}
return result;
}
static Uint32
VIRTUAL_JoystickGetCapabilities(SDL_Joystick *joystick)
{
return 0;
joystick_hwdata *hwdata = joystick->hwdata;
Uint32 caps = 0;
if (hwdata) {
if (hwdata->desc.Rumble) {
caps |= SDL_JOYCAP_RUMBLE;
}
if (hwdata->desc.RumbleTriggers) {
caps |= SDL_JOYCAP_RUMBLE_TRIGGERS;
}
if (hwdata->desc.SetLED) {
caps |= SDL_JOYCAP_LED;
}
}
return caps;
}
static int
VIRTUAL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
int result;
if (joystick->hwdata) {
joystick_hwdata *hwdata = joystick->hwdata;
if (hwdata->desc.SetLED) {
result = hwdata->desc.SetLED(hwdata->desc.userdata, red, green, blue);
} else {
result = SDL_Unsupported();
}
} else {
result = SDL_SetError("SetLED failed, device disconnected");
}
return result;
}
static int
VIRTUAL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
{
return SDL_Unsupported();
int result;
if (joystick->hwdata) {
joystick_hwdata *hwdata = joystick->hwdata;
if (hwdata->desc.SendEffect) {
result = hwdata->desc.SendEffect(hwdata->desc.userdata, data, size);
} else {
result = SDL_Unsupported();
}
} else {
result = SDL_SetError("SendEffect failed, device disconnected");
}
return result;
}
static int
@ -386,13 +576,17 @@ VIRTUAL_JoystickUpdate(SDL_Joystick *joystick)
hwdata = (joystick_hwdata *)joystick->hwdata;
for (i = 0; i < hwdata->naxes; ++i) {
if (hwdata->desc.Update) {
hwdata->desc.Update(hwdata->desc.userdata);
}
for (i = 0; i < hwdata->desc.naxes; ++i) {
SDL_PrivateJoystickAxis(joystick, i, hwdata->axes[i]);
}
for (i = 0; i < hwdata->nbuttons; ++i) {
for (i = 0; i < hwdata->desc.nbuttons; ++i) {
SDL_PrivateJoystickButton(joystick, i, hwdata->buttons[i]);
}
for (i = 0; i < hwdata->nhats; ++i) {
for (i = 0; i < hwdata->desc.nhats; ++i) {
SDL_PrivateJoystickHat(joystick, i, hwdata->hats[i]);
}
}
@ -401,17 +595,11 @@ VIRTUAL_JoystickUpdate(SDL_Joystick *joystick)
static void
VIRTUAL_JoystickClose(SDL_Joystick *joystick)
{
joystick_hwdata *hwdata;
if (!joystick) {
return;
if (joystick->hwdata) {
joystick_hwdata *hwdata = joystick->hwdata;
hwdata->joystick = NULL;
joystick->hwdata = NULL;
}
if (!joystick->hwdata) {
return;
}
hwdata = (joystick_hwdata *)joystick->hwdata;
hwdata->opened = SDL_FALSE;
}
@ -426,7 +614,145 @@ VIRTUAL_JoystickQuit(void)
static SDL_bool
VIRTUAL_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
{
return SDL_FALSE;
joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
int current_button = 0;
int current_axis = 0;
if (hwdata->desc.type != SDL_JOYSTICK_TYPE_GAMECONTROLLER) {
return SDL_FALSE;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_A))) {
out->a.kind = EMappingKind_Button;
out->a.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_B))) {
out->b.kind = EMappingKind_Button;
out->b.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_X))) {
out->x.kind = EMappingKind_Button;
out->x.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_Y))) {
out->y.kind = EMappingKind_Button;
out->y.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_BACK))) {
out->back.kind = EMappingKind_Button;
out->back.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_GUIDE))) {
out->guide.kind = EMappingKind_Button;
out->guide.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_START))) {
out->start.kind = EMappingKind_Button;
out->start.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_LEFTSTICK))) {
out->leftstick.kind = EMappingKind_Button;
out->leftstick.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_RIGHTSTICK))) {
out->rightstick.kind = EMappingKind_Button;
out->rightstick.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_LEFTSHOULDER))) {
out->leftshoulder.kind = EMappingKind_Button;
out->leftshoulder.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_RIGHTSHOULDER))) {
out->rightshoulder.kind = EMappingKind_Button;
out->rightshoulder.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_UP))) {
out->dpup.kind = EMappingKind_Button;
out->dpup.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN))) {
out->dpdown.kind = EMappingKind_Button;
out->dpdown.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT))) {
out->dpleft.kind = EMappingKind_Button;
out->dpleft.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT))) {
out->dpright.kind = EMappingKind_Button;
out->dpright.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_MISC1))) {
out->misc1.kind = EMappingKind_Button;
out->misc1.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_PADDLE1))) {
out->paddle1.kind = EMappingKind_Button;
out->paddle1.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_PADDLE2))) {
out->paddle2.kind = EMappingKind_Button;
out->paddle2.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_PADDLE3))) {
out->paddle3.kind = EMappingKind_Button;
out->paddle3.target = current_button++;
}
if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_CONTROLLER_BUTTON_PADDLE4))) {
out->paddle4.kind = EMappingKind_Button;
out->paddle4.target = current_button++;
}
if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_CONTROLLER_AXIS_LEFTX))) {
out->leftx.kind = EMappingKind_Axis;
out->leftx.target = current_axis++;
}
if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_CONTROLLER_AXIS_LEFTY))) {
out->lefty.kind = EMappingKind_Axis;
out->lefty.target = current_axis++;
}
if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_CONTROLLER_AXIS_RIGHTX))) {
out->rightx.kind = EMappingKind_Axis;
out->rightx.target = current_axis++;
}
if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_CONTROLLER_AXIS_RIGHTY))) {
out->righty.kind = EMappingKind_Axis;
out->righty.target = current_axis++;
}
if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_CONTROLLER_AXIS_TRIGGERLEFT))) {
out->lefttrigger.kind = EMappingKind_Axis;
out->lefttrigger.target = current_axis++;
}
if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_CONTROLLER_AXIS_TRIGGERRIGHT))) {
out->righttrigger.kind = EMappingKind_Axis;
out->righttrigger.target = current_axis++;
}
return SDL_TRUE;
}
SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver =
@ -435,6 +761,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver =
VIRTUAL_JoystickGetCount,
VIRTUAL_JoystickDetect,
VIRTUAL_JoystickGetDeviceName,
VIRTUAL_JoystickGetDevicePath,
VIRTUAL_JoystickGetDevicePlayerIndex,
VIRTUAL_JoystickSetDevicePlayerIndex,
VIRTUAL_JoystickGetDeviceGUID,

View file

@ -34,24 +34,19 @@ typedef struct joystick_hwdata
{
SDL_JoystickType type;
SDL_bool attached;
const char *name;
char *name;
SDL_JoystickGUID guid;
int naxes;
SDL_VirtualJoystickDesc desc;
Sint16 *axes;
int nbuttons;
Uint8 *buttons;
int nhats;
Uint8 *hats;
SDL_JoystickID instance_id;
SDL_bool opened;
SDL_Joystick *joystick;
struct joystick_hwdata *next;
} joystick_hwdata;
int SDL_JoystickAttachVirtualInner(SDL_JoystickType type,
int naxes,
int nbuttons,
int nhats);
int SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc);
int SDL_JoystickDetachVirtualInner(int device_index);
int SDL_JoystickSetVirtualAxisInner(SDL_Joystick * joystick, int axis, Sint16 value);
@ -59,4 +54,7 @@ int SDL_JoystickSetVirtualButtonInner(SDL_Joystick * joystick, int button, Uint8
int SDL_JoystickSetVirtualHatInner(SDL_Joystick * joystick, int hat, Uint8 value);
#endif /* SDL_JOYSTICK_VIRTUAL */
#endif /* SDL_VIRTUALJOYSTICK_C_H */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -179,7 +179,6 @@ SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index)
return device_index;
}
/* Function to get the device-dependent name of a joystick */
const char *VITA_JoystickGetDeviceName(int index)
{
if (index == 0)
@ -195,7 +194,12 @@ const char *VITA_JoystickGetDeviceName(int index)
return "PSVita Controller";
SDL_SetError("No joystick available with that index");
return(NULL);
return NULL;
}
const char *VITA_JoystickGetDevicePath(int index)
{
return NULL;
}
static int
@ -400,6 +404,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver =
VITA_JoystickGetCount,
VITA_JoystickDetect,
VITA_JoystickGetDeviceName,
VITA_JoystickGetDevicePath,
VITA_JoystickGetDevicePlayerIndex,
VITA_JoystickSetDevicePlayerIndex,
VITA_JoystickGetDeviceGUID,

View file

@ -456,7 +456,7 @@ EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
pNewJoystick = *(JoyStick_DeviceData**)pContext;
while (pNewJoystick) {
/* update GUIDs of joysticks with matching paths, in case they're not open yet */
if (SDL_strcmp(pNewJoystick->hidPath, hidPath) == 0) {
if (SDL_strcmp(pNewJoystick->path, hidPath) == 0) {
/* if we are replacing the front of the list then update it */
if (pNewJoystick == *(JoyStick_DeviceData**)pContext) {
*(JoyStick_DeviceData**)pContext = pNewJoystick->pNext;
@ -483,7 +483,7 @@ EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
CHECK(pNewJoystick);
SDL_zerop(pNewJoystick);
SDL_strlcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath));
SDL_strlcpy(pNewJoystick->path, hidPath, SDL_arraysize(pNewJoystick->path));
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));
SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
@ -683,7 +683,7 @@ EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE pDeviceObject, LPVOID pContext)
/* Sort using the data offset into the DInput struct.
* This gives a reasonable ordering for the inputs.
*/
static int
static int SDLCALL
SortDevFunc(const void *a, const void *b)
{
const input_t *inputA = (const input_t*)a;

View file

@ -105,6 +105,7 @@ typedef struct _SDL_RAWINPUT_Device
{
SDL_atomic_t refcount;
char *name;
char *path;
Uint16 vendor_id;
Uint16 product_id;
Uint16 version;
@ -689,10 +690,9 @@ RAWINPUT_ReleaseDevice(SDL_RAWINPUT_Device *device)
#endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
if (SDL_AtomicDecRef(&device->refcount)) {
if (device->preparsed_data) {
SDL_HidD_FreePreparsedData(device->preparsed_data);
}
SDL_free(device->preparsed_data);
SDL_free(device->name);
SDL_free(device->path);
SDL_free(device);
}
}
@ -716,9 +716,8 @@ RAWINPUT_AddDevice(HANDLE hDevice)
SDL_RAWINPUT_Device *device = NULL;
SDL_RAWINPUT_Device *curr, *last;
RID_DEVICE_INFO rdi;
UINT rdi_size = sizeof(rdi);
UINT size;
char dev_name[MAX_PATH];
UINT name_size = SDL_arraysize(dev_name);
HANDLE hFile = INVALID_HANDLE_VALUE;
/* Make sure we're not trying to add the same device twice */
@ -727,11 +726,13 @@ RAWINPUT_AddDevice(HANDLE hDevice)
}
/* Figure out what kind of device it is */
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICEINFO, &rdi, &rdi_size) != (UINT)-1);
size = sizeof(rdi);
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICEINFO, &rdi, &size) != (UINT)-1);
CHECK(rdi.dwType == RIM_TYPEHID);
/* Get the device "name" (HID Path) */
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &name_size) != (UINT)-1);
size = SDL_arraysize(dev_name);
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &size) != (UINT)-1);
/* Only take XInput-capable devices */
CHECK(SDL_strstr(dev_name, "IG_") != NULL);
#ifdef SDL_JOYSTICK_HIDAPI
@ -747,6 +748,12 @@ RAWINPUT_AddDevice(HANDLE hDevice)
device->is_xinput = SDL_TRUE;
device->is_xboxone = GuessControllerType(device->vendor_id, device->product_id) == k_eControllerType_XBoxOneController;
/* Get HID Top-Level Collection Preparsed Data */
size = 0;
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_PREPARSEDDATA, NULL, &size) != (UINT)-1);
CHECK(device->preparsed_data = (PHIDP_PREPARSED_DATA)SDL_calloc(size, sizeof(BYTE)));
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_PREPARSEDDATA, device->preparsed_data, &size) != (UINT)-1);
{
const Uint16 vendor = device->vendor_id;
const Uint16 product = device->product_id;
@ -791,8 +798,7 @@ RAWINPUT_AddDevice(HANDLE hDevice)
SDL_free(product_string);
}
}
CHECK(SDL_HidD_GetPreparsedData(hFile, &device->preparsed_data));
device->path = SDL_strdup(dev_name);
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
@ -825,8 +831,12 @@ err:
CloseHandle(hFile);
}
if (device) {
if (device->name)
if (device->name) {
SDL_free(device->name);
}
if (device->path) {
SDL_free(device->path);
}
SDL_free(device);
}
#undef CHECK
@ -1029,6 +1039,12 @@ RAWINPUT_JoystickGetDeviceName(int device_index)
return RAWINPUT_GetDeviceByIndex(device_index)->name;
}
static const char *
RAWINPUT_JoystickGetDevicePath(int device_index)
{
return RAWINPUT_GetDeviceByIndex(device_index)->path;
}
static int
RAWINPUT_JoystickGetDevicePlayerIndex(int device_index)
{
@ -1053,7 +1069,7 @@ RAWINPUT_JoystickGetDeviceInstanceID(int device_index)
return RAWINPUT_GetDeviceByIndex(device_index)->joystick_id;
}
static int
static int SDLCALL
RAWINPUT_SortValueCaps(const void *A, const void *B)
{
HIDP_VALUE_CAPS *capsA = (HIDP_VALUE_CAPS *)A;
@ -1253,7 +1269,7 @@ RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
}
}
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_UNKNOWN);
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
return 0;
}
@ -1263,8 +1279,8 @@ RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uin
{
#if defined(SDL_JOYSTICK_RAWINPUT_WGI) || defined(SDL_JOYSTICK_RAWINPUT_XINPUT)
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
SDL_bool rumbled = SDL_FALSE;
#endif
SDL_bool rumbled = SDL_FALSE;
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
if (!rumbled && ctx->wgi_correlated) {
@ -1312,7 +1328,7 @@ RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
{
#if defined(SDL_JOYSTICK_RAWINPUT_WGI)
RAWINPUT_DeviceContext *ctx = joystick->hwdata;
if (ctx->wgi_correlated) {
WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
HRESULT hr;
@ -1570,17 +1586,25 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
int guide_button = joystick->nbuttons - 1;
int left_trigger = joystick->naxes - 2;
int right_trigger = joystick->naxes - 1;
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
SDL_bool xinput_correlated;
#endif
RAWINPUT_FillMatchState(&match_state_xinput, ctx->match_state);
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
xinput_correlated = ctx->xinput_correlated;
#else
xinput_correlated = SDL_FALSE;
#endif
/* Parallel logic to WINDOWS_XINPUT below */
RAWINPUT_UpdateWindowsGamingInput();
if (ctx->wgi_correlated &&
!joystick->low_frequency_rumble && !joystick->high_frequency_rumble &&
!joystick->left_trigger_rumble && !joystick->right_trigger_rumble) {
/* We have been previously correlated, ensure we are still matching, see comments in XINPUT section */
if (RAWINPUT_WindowsGamingInputSlotMatches(&match_state_xinput, ctx->wgi_slot, ctx->xinput_correlated)) {
if (RAWINPUT_WindowsGamingInputSlotMatches(&match_state_xinput, ctx->wgi_slot, xinput_correlated)) {
ctx->wgi_uncorrelate_count = 0;
} else {
++ctx->wgi_uncorrelate_count;
@ -1609,7 +1633,7 @@ RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
if (RAWINPUT_MissingWindowsGamingInputSlot()) {
Uint8 correlation_id;
WindowsGamingInputGamepadState *slot_idx = NULL;
if (RAWINPUT_GuessWindowsGamingInputSlot(&match_state_xinput, &correlation_id, &slot_idx, ctx->xinput_correlated)) {
if (RAWINPUT_GuessWindowsGamingInputSlot(&match_state_xinput, &correlation_id, &slot_idx, xinput_correlated)) {
/* we match exactly one WindowsGamingInput device */
/* Probably can do without wgi_correlation_count, just check and clear wgi_slot to NULL, unless we need
even more frames to be sure. */
@ -1911,7 +1935,7 @@ RAWINPUT_UnregisterNotifications()
return;
}
}
LRESULT CALLBACK
RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@ -2006,6 +2030,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver =
RAWINPUT_JoystickGetCount,
RAWINPUT_JoystickDetect,
RAWINPUT_JoystickGetDeviceName,
RAWINPUT_JoystickGetDevicePath,
RAWINPUT_JoystickGetDevicePlayerIndex,
RAWINPUT_JoystickSetDevicePlayerIndex,
RAWINPUT_JoystickGetDeviceGUID,

View file

@ -586,6 +586,12 @@ WGI_JoystickGetDeviceName(int device_index)
return wgi.controllers[device_index].name;
}
static const char *
WGI_JoystickGetDevicePath(int device_index)
{
return NULL;
}
static int
WGI_JoystickGetDevicePlayerIndex(int device_index)
{
@ -893,6 +899,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver =
WGI_JoystickGetCount,
WGI_JoystickDetect,
WGI_JoystickGetDeviceName,
WGI_JoystickGetDevicePath,
WGI_JoystickGetDevicePlayerIndex,
WGI_JoystickSetDevicePlayerIndex,
WGI_JoystickGetDeviceGUID,

View file

@ -330,7 +330,7 @@ SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, SDL_mutex *mutex
static SDL_DeviceNotificationData s_notification_data;
/* Function/thread to scan the system for joysticks. */
static int
static int SDLCALL
SDL_JoystickThread(void *_data)
{
#if SDL_JOYSTICK_XINPUT
@ -555,7 +555,6 @@ WINDOWS_JoystickDetect(void)
}
}
/* Function to get the device-dependent name of a joystick */
static const char *
WINDOWS_JoystickGetDeviceName(int device_index)
{
@ -568,6 +567,18 @@ WINDOWS_JoystickGetDeviceName(int device_index)
return device->joystickname;
}
static const char *
WINDOWS_JoystickGetDevicePath(int device_index)
{
JoyStick_DeviceData *device = SYS_Joystick;
int index;
for (index = device_index; index > 0; index--)
device = device->pNext;
return device->path;
}
static int
WINDOWS_JoystickGetDevicePlayerIndex(int device_index)
{
@ -755,6 +766,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
WINDOWS_JoystickGetCount,
WINDOWS_JoystickDetect,
WINDOWS_JoystickGetDeviceName,
WINDOWS_JoystickGetDevicePath,
WINDOWS_JoystickGetDevicePlayerIndex,
WINDOWS_JoystickSetDevicePlayerIndex,
WINDOWS_JoystickGetDeviceGUID,

View file

@ -37,7 +37,7 @@ typedef struct JoyStick_DeviceData
BYTE SubType;
Uint8 XInputUserId;
DIDEVICEINSTANCE dxdevice;
char hidPath[MAX_PATH];
char path[MAX_PATH];
struct JoyStick_DeviceData *pNext;
} JoyStick_DeviceData;

View file

@ -297,6 +297,7 @@ AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
SDL_free(pNewJoystick);
return; /* better luck next time? */
}
SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%d", userid);
if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
SDL_free(pNewJoystick);