From 9b256d71a9eb142654de96fdafdcbfda00cf64fe Mon Sep 17 00:00:00 2001 From: Florin9doi Date: Mon, 5 Jan 2026 16:52:26 +0200 Subject: [PATCH] USB: Fixed G27 crash during reinitialization --- BUILDING.md | 2 +- rpcs3/Emu/Cell/lv2/sys_usbd.cpp | 38 ++++++++++++++++++++------------- rpcs3/Emu/Io/LogitechG27.cpp | 10 ++++----- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 32cdc6cc03..26295d0a16 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -51,7 +51,7 @@ These are the essentials tools to build RPCS3 on Linux. Some of them can be inst #### Debian & Ubuntu - sudo apt-get install build-essential ninja-build libasound2-dev libpulse-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git libevdev-dev libsdl3-3.2 libsdl3-dev libjack-dev libsndio-dev + sudo apt-get install build-essential ninja-build libasound2-dev libpulse-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git libevdev-dev libsdl3-dev libjack-dev libsndio-dev libcurl4-openssl-dev qt6-base-dev qt6-base-private-dev qt6-multimedia-dev qt6-svg-dev libxkbcommon-dev Ubuntu is usually horrendously out of date, and some packages need to be downloaded by hand. This part is for Qt, GCC, Vulkan, and CMake diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index 463ec7a68d..3afa2a9e06 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -137,6 +137,7 @@ public: const std::array& get_new_location(); void connect_usb_device(std::shared_ptr dev, bool update_usb_devices = false); void disconnect_usb_device(std::shared_ptr dev, bool update_usb_devices = false); + void reconnect_usb_device(u32 assigned_number); // Map of devices actively handled by the ps3(device_id, device) std::map>> handled_devices; @@ -205,19 +206,23 @@ private: {0x1BAD, 0x3430, 0x343F, "Harmonix Button Guitar - Wii", nullptr, nullptr}, {0x1BAD, 0x3530, 0x353F, "Harmonix Real Guitar - Wii", nullptr, nullptr}, - //Top Shot Elite controllers + // Top Shot Elite controllers {0x12BA, 0x04A0, 0x04A0, "Top Shot Elite", nullptr, nullptr}, {0x12BA, 0x04A1, 0x04A1, "Top Shot Fearmaster", nullptr, nullptr}, {0x12BA, 0x04B0, 0x04B0, "Rapala Fishing Rod", nullptr, nullptr}, - // GT5 Wheels&co + // Wheels #ifdef HAVE_SDL3 {0x046D, 0xC283, 0xC29B, "lgFF_c283_c29b", &usb_device_logitech_g27::get_num_emu_devices, &usb_device_logitech_g27::make_instance}, #else {0x046D, 0xC283, 0xC29B, "lgFF_c283_c29b", nullptr, nullptr}, #endif + {0x046D, 0xCA03, 0xCA03, "lgFF_ca03_ca03", nullptr, nullptr}, + {0x044F, 0xB652, 0xB652, "Thrustmaster FGT FFB old", nullptr, nullptr}, {0x044F, 0xB653, 0xB653, "Thrustmaster RGT FFB Pro", nullptr, nullptr}, + {0x044F, 0xB654, 0xB654, "Thrustmaster FGT FFB", nullptr, nullptr}, + {0x044F, 0xb655, 0xb655, "Thrustmaster FGT Rumble 3-in-1", nullptr, nullptr}, {0x044F, 0xB65A, 0xB65A, "Thrustmaster F430", nullptr, nullptr}, {0x044F, 0xB65D, 0xB65D, "Thrustmaster FFB", nullptr, nullptr}, {0x044F, 0xB65E, 0xB65E, "Thrustmaster TRS", nullptr, nullptr}, @@ -225,7 +230,6 @@ private: // GT6 {0x2833, 0x0001, 0x0001, "Oculus", nullptr, nullptr}, - {0x046D, 0xCA03, 0xCA03, "lgFF_ca03_ca03", nullptr, nullptr}, // Buzz controllers {0x054C, 0x1000, 0x1040, "buzzer0", &usb_device_buzz::get_num_emu_devices, &usb_device_buzz::make_instance}, @@ -968,6 +972,21 @@ void usb_handler_thread::disconnect_usb_device(std::shared_ptr dev, } } +void usb_handler_thread::reconnect_usb_device(u32 assigned_number) +{ + std::lock_guard lock(mutex); + ensure(assigned_number != 0); + for (const auto& dev : usb_devices) + { + if (dev->assigned_number == assigned_number) + { + disconnect_usb_device(dev, false); + connect_usb_device(dev, false); + break; + } + } +} + void connect_usb_controller(u8 index, input::product_type type) { auto usbh = g_fxo->try_get>(); @@ -1061,18 +1080,7 @@ void reconnect_usb(u32 assigned_number) { return; } - - std::lock_guard lock(usbh->mutex); - for (auto& [nr, pair] : usbh->handled_devices) - { - auto& [internal_dev, dev] = pair; - if (nr == assigned_number) - { - usbh->disconnect_usb_device(dev, false); - usbh->connect_usb_device(dev, false); - break; - } - } + usbh->reconnect_usb_device(assigned_number); } void handle_hotplug_event(bool connected) diff --git a/rpcs3/Emu/Io/LogitechG27.cpp b/rpcs3/Emu/Io/LogitechG27.cpp index c8aa453592..2eb62581bb 100644 --- a/rpcs3/Emu/Io/LogitechG27.cpp +++ b/rpcs3/Emu/Io/LogitechG27.cpp @@ -1752,7 +1752,7 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp { if (!SDL_RunHapticEffect(m_haptic_handle, m_effect_slots[i].effect_id, 1)) { - logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s\n", m_effect_slots[i].last_effect.type, i, SDL_GetError()); + logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s", m_effect_slots[i].last_effect.type, i, SDL_GetError()); } } else @@ -1796,14 +1796,14 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp { if (!SDL_RunHapticEffect(m_haptic_handle, m_effect_slots[i].effect_id, 1)) { - logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s\n", m_effect_slots[i].last_effect.type, i, SDL_GetError()); + logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s", m_effect_slots[i].last_effect.type, i, SDL_GetError()); } } else { if (!SDL_StopHapticEffect(m_haptic_handle, m_effect_slots[i].effect_id)) { - logitech_g27_log.error("Failed stopping sdl effect %d on slot %d, %s\n", m_effect_slots[i].last_effect.type, i, SDL_GetError()); + logitech_g27_log.error("Failed stopping sdl effect %d on slot %d, %s", m_effect_slots[i].last_effect.type, i, SDL_GetError()); } } } @@ -1824,11 +1824,11 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp { if (cmd == 0x02) { - logitech_g27_log.error("Tried to play effect slot %d but it was never uploaded\n", i); + logitech_g27_log.error("Tried to play effect slot %d but it was never uploaded", i); } else { - logitech_g27_log.error("Tried to stop effect slot %d but it was never uploaded\n", i); + logitech_g27_log.error("Tried to stop effect slot %d but it was never uploaded", i); } } }