IOS/USB: Fix initial device scan

Even though libusb is supposed to be thread-safe, in practice
it's not (at least on Windows); getting a list of devices from two
different threads can result in libusb crashes. This is easily
fixed by waiting for the scan thread to complete scanning instead
of running the scan on the CPU thread.

This also fixes an issue that I had overlooked in the initial
implementation: IOS interfaces such as OH0 are sometimes opened
every frame, in which case we were doing a full device scan every
single frame on the CPU thread!
This commit is contained in:
Léo Lam 2019-05-04 12:23:57 +02:00
parent b274a054a9
commit 2b44e1b851
2 changed files with 10 additions and 4 deletions

View File

@ -45,12 +45,14 @@ USBHost::~USBHost()
IPCCommandResult USBHost::Open(const OpenRequest& request)
{
// Force a device scan to complete, because some games (including Your Shape) only care
// about the initial device list (in the first GETDEVICECHANGE reply).
while (!UpdateDevices())
if (!m_has_initialised)
{
StartThreads();
// Force a device scan to complete, because some games (including Your Shape) only care
// about the initial device list (in the first GETDEVICECHANGE reply).
m_first_scan_complete_event.Wait();
m_has_initialised = true;
}
StartThreads();
return GetDefaultReply(IPC_SUCCESS);
}
@ -117,6 +119,7 @@ bool USBHost::UpdateDevices(const bool always_add_hooks)
return false;
DetectRemovedDevices(plugged_devices, hooks);
DispatchHooks(hooks);
m_first_scan_complete_event.Set();
return true;
}

View File

@ -15,6 +15,7 @@
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/Event.h"
#include "Common/Flag.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h"
@ -76,5 +77,7 @@ private:
// Device scanning thread
Common::Flag m_scan_thread_running;
std::thread m_scan_thread;
Common::Event m_first_scan_complete_event;
bool m_has_initialised = false;
};
} // namespace IOS::HLE::Device