Hotplug support for emulated devices

This commit is contained in:
Florin9doi 2024-05-12 12:49:18 +03:00 committed by Megamouse
parent 941c87f6d7
commit 65455b454e
2 changed files with 65 additions and 8 deletions

View file

@ -108,8 +108,13 @@ public:
std::pair<u32, UsbDeviceIsoRequest> get_isochronous_transfer_status(u32 transfer_id);
void push_fake_transfer(UsbTransfer* transfer);
const std::array<u8, 7>& get_new_location();
void connect_usb_device(std::shared_ptr<usb_device> dev);
void disconnect_usb_device(std::shared_ptr<usb_device> dev);
// Map of devices actively handled by the ps3(device_id, device)
std::map<u32, std::pair<UsbInternalDevice, std::shared_ptr<usb_device>>> handled_devices;
std::map<u8, std::pair<input::product_type, std::shared_ptr<usb_device>>> pad_to_usb;
shared_mutex mutex;
atomic_t<bool> is_init = false;
@ -147,6 +152,7 @@ private:
std::queue<std::tuple<u64, u64, u64>> usbd_events;
// List of devices "connected" to the ps3
std::array<u8, 7> location{};
std::vector<std::shared_ptr<usb_device>> usb_devices;
libusb_context* ctx = nullptr;
@ -229,14 +235,6 @@ usb_handler_thread::usb_handler_thread()
return;
}
std::array<u8, 7> location{};
auto get_new_location = [&]() -> const std::array<u8, 7>&
{
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<u8, 7>& usb_handler_thread::get_new_location()
{
location[0]++;
return location;
}
void usb_handler_thread::connect_usb_device(std::shared_ptr<usb_device> 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<u8>(assigned_number), narrow<u8>(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<usb_device> 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<named_thread<usb_handler_thread>>();
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<u32> handle)
{
ppu.state += cpu_flag::wait;

View file

@ -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<char> 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<char> s_product, u16 slen_product);
void connect_usb_controller(u8 index, input::product_type);