diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 4449d0af0..b557d0c67 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -71,6 +71,10 @@ 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; @@ -434,16 +438,12 @@ VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index) if (!hwdata) { return SDL_SetError("No such device"); } - if (hwdata->opened) { - /* This should never happen, it's handled by the higher joystick code */ - return SDL_SetError("Joystick already opened"); - } joystick->instance_id = hwdata->instance_id; joystick->hwdata = hwdata; joystick->naxes = hwdata->desc.naxes; joystick->nbuttons = hwdata->desc.nbuttons; joystick->nhats = hwdata->desc.nhats; - hwdata->opened = SDL_TRUE; + hwdata->joystick = joystick; return 0; } @@ -451,23 +451,39 @@ VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index) static int VIRTUAL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) { - joystick_hwdata *hwdata = joystick->hwdata; + int result; - if (hwdata && hwdata->desc.Rumble) { - return hwdata->desc.Rumble(hwdata->desc.userdata, low_frequency_rumble, high_frequency_rumble); + 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 SDL_Unsupported(); + + return result; } static int VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) { - joystick_hwdata *hwdata = joystick->hwdata; + int result; - if (hwdata && hwdata->desc.RumbleTriggers) { - return hwdata->desc.RumbleTriggers(hwdata->desc.userdata, left_rumble, right_rumble); + 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 SDL_Unsupported(); + + return result; } @@ -495,23 +511,39 @@ VIRTUAL_JoystickGetCapabilities(SDL_Joystick *joystick) static int VIRTUAL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { - joystick_hwdata *hwdata = joystick->hwdata; + int result; - if (hwdata && hwdata->desc.SetLED) { - return hwdata->desc.SetLED(hwdata->desc.userdata, red, green, blue); + 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 SDL_Unsupported(); + + return result; } static int VIRTUAL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) { - joystick_hwdata *hwdata = joystick->hwdata; + int result; - if (hwdata && hwdata->desc.SendEffect) { - return hwdata->desc.SendEffect(hwdata->desc.userdata, data, size); + 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 SDL_Unsupported(); + + return result; } static int @@ -555,17 +587,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; } diff --git a/src/joystick/virtual/SDL_virtualjoystick_c.h b/src/joystick/virtual/SDL_virtualjoystick_c.h index a12d6c84a..5e15f1dd6 100644 --- a/src/joystick/virtual/SDL_virtualjoystick_c.h +++ b/src/joystick/virtual/SDL_virtualjoystick_c.h @@ -41,7 +41,8 @@ typedef struct joystick_hwdata Uint8 *buttons; Uint8 *hats; SDL_JoystickID instance_id; - SDL_bool opened; + SDL_Joystick *joystick; + struct joystick_hwdata *next; } joystick_hwdata; diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index b24581598..45560c5da 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -335,9 +335,10 @@ static int VirtualControllerSetLED(void *userdata, Uint8 red, Uint8 green, Uint8 return 0; } -static int OpenVirtualController() +static void OpenVirtualController() { SDL_VirtualJoystickDesc desc; + int virtual_index; SDL_zero(desc); desc.version = SDL_VIRTUAL_JOYSTICK_DESC_VERSION; @@ -348,7 +349,32 @@ static int OpenVirtualController() desc.Rumble = VirtualControllerRumble; desc.RumbleTriggers = VirtualControllerRumbleTriggers; desc.SetLED = VirtualControllerSetLED; - return SDL_JoystickAttachVirtualEx(&desc); + + virtual_index = SDL_JoystickAttachVirtualEx(&desc); + if (virtual_index < 0) { + SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError()); + } else { + virtual_joystick = SDL_JoystickOpen(virtual_index); + if (!virtual_joystick) { + SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError()); + } + } +} + +static void CloseVirtualController() +{ + int i; + + for (i = 0; i < SDL_NumJoysticks(); ++i) { + if (SDL_JoystickIsVirtual(i)) { + SDL_JoystickDetachVirtual(i); + } + } + + if (virtual_joystick) { + SDL_JoystickClose(virtual_joystick); + virtual_joystick = NULL; + } } static SDL_GameControllerButton FindButtonAtPosition(int x, int y) @@ -580,6 +606,14 @@ loop(void *arg) } break; } + if (event.key.keysym.sym == SDLK_a) { + OpenVirtualController(); + break; + } + if (event.key.keysym.sym == SDLK_d) { + CloseVirtualController(); + break; + } if (event.key.keysym.sym != SDLK_ESCAPE) { break; } @@ -836,15 +870,7 @@ main(int argc, char *argv[]) for (i = 1; i < argc; ++i) { if (SDL_strcmp(argv[i], "--virtual") == 0) { - int virtual_index = OpenVirtualController(); - if (virtual_index < 0) { - SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError()); - } else { - virtual_joystick = SDL_JoystickOpen(virtual_index); - if (!virtual_joystick) { - SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError()); - } - } + OpenVirtualController(); } if (argv[i] && *argv[i] != '-') { controller_index = SDL_atoi(argv[i]); @@ -873,6 +899,7 @@ main(int argc, char *argv[]) CyclePS5TriggerEffect(); } + CloseVirtualController(); SDL_DestroyRenderer(screen); SDL_DestroyWindow(window); SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);