From 65455b454efd299125a8ebfd690b388fca65fd81 Mon Sep 17 00:00:00 2001 From: Florin9doi Date: Sun, 12 May 2024 12:49:18 +0300 Subject: [PATCH] Hotplug support for emulated devices --- rpcs3/Emu/Cell/lv2/sys_usbd.cpp | 70 +++++++++++++++++++++++++++++---- rpcs3/Emu/Cell/lv2/sys_usbd.h | 3 ++ 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index 7844d8901d..db38f9f629 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -108,8 +108,13 @@ public: std::pair get_isochronous_transfer_status(u32 transfer_id); void push_fake_transfer(UsbTransfer* transfer); + const std::array& get_new_location(); + void connect_usb_device(std::shared_ptr dev); + void disconnect_usb_device(std::shared_ptr dev); + // Map of devices actively handled by the ps3(device_id, device) std::map>> handled_devices; + std::map>> pad_to_usb; shared_mutex mutex; atomic_t is_init = false; @@ -147,6 +152,7 @@ private: std::queue> usbd_events; // List of devices "connected" to the ps3 + std::array location{}; std::vector> usb_devices; libusb_context* ctx = nullptr; @@ -229,14 +235,6 @@ usb_handler_thread::usb_handler_thread() return; } - std::array location{}; - - auto get_new_location = [&]() -> const std::array& - { - location[0]++; - return location; - }; - bool found_skylander = false; bool found_infinity = false; bool found_usj = false; @@ -814,6 +812,62 @@ void usb_handler_thread::push_fake_transfer(UsbTransfer* transfer) fake_transfers.push_back(transfer); } +const std::array& usb_handler_thread::get_new_location() +{ + location[0]++; + return location; +} + +void usb_handler_thread::connect_usb_device(std::shared_ptr new_dev) +{ + usb_devices.push_back(new_dev); + + for (const auto& [name, ldd] : ldds) + { + sys_usbd.success("connect_usb_device : check ldd : name=%s VID=%04x, PID=%04x->%04x", name, ldd.id_vendor, ldd.id_product_min, ldd.id_product_max); + if (new_dev->device._device.idVendor == ldd.id_vendor && new_dev->device._device.idProduct >= ldd.id_product_min && new_dev->device._device.idProduct <= ldd.id_product_max) + { + const int assigned_number = dev_counter++; + handled_devices.emplace(assigned_number, std::pair(UsbInternalDevice{narrow(assigned_number), narrow(assigned_number), 0x00, 0x00}, new_dev)); + new_dev->assigned_number = assigned_number; + send_message(SYS_USBD_ATTACH, assigned_number); + sys_usbd.success("connect_usb_device : ldds already registered : assigned_number = %d", assigned_number); + } + } +} + +void usb_handler_thread::disconnect_usb_device(std::shared_ptr dev) +{ + if (dev->assigned_number && handled_devices.erase(dev->assigned_number)) + { + sys_usbd.success("disconnect_usb_device : detach device %d", dev->assigned_number); + send_message(SYS_USBD_DETACH, dev->assigned_number); + dev->assigned_number = 0; + } + + usb_devices.erase(find(usb_devices.begin(), usb_devices.end(), dev)); +} + +void connect_usb_controller(u8 index, input::product_type type) +{ + bool already_connected = false; + auto& usbh = g_fxo->get>(); + + if (const auto it = usbh.pad_to_usb.find(index); it != usbh.pad_to_usb.end()) + { + if (it->second.first == type) + { + already_connected = true; + } + else + { + usbh.disconnect_usb_device(it->second.second); + usbh.pad_to_usb.erase(it->first); + } + } +} + + error_code sys_usbd_initialize(ppu_thread& ppu, vm::ptr handle) { ppu.state += cpu_flag::wait; diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.h b/rpcs3/Emu/Cell/lv2/sys_usbd.h index 622c9e718d..9c81fb7b80 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.h +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.h @@ -2,6 +2,7 @@ #include "Emu/Memory/vm_ptr.h" #include "Emu/Cell/ErrorCodes.h" +#include "Input/product_info.h" class ppu_thread; @@ -86,3 +87,5 @@ error_code sys_usbd_free_memory(ppu_thread& ppu); error_code sys_usbd_get_device_speed(ppu_thread& ppu); error_code sys_usbd_register_extra_ldd(ppu_thread& ppu, u32 handle, vm::cptr s_product, u16 slen_product, u16 id_vendor, u16 id_product_min, u16 id_product_max); error_code sys_usbd_unregister_extra_ldd(ppu_thread& ppu, u32 handle, vm::cptr s_product, u16 slen_product); + +void connect_usb_controller(u8 index, input::product_type);