IOS: Remove from m_opened_devices in OH0::OnDeviceChange

I've been playing Rock Band 3 recently and have experienced a bug where
sometimes if you disconnect and reconnect a USB microphone, the game
won't pick up on it connecting, not even it you disconnect and reconnect
it again. An investigation into what's going on inside Dolphin shows
that when the game triggers a call to OH0::DeviceOpen after the device
has been reinserted, Dolphin doesn't open the device because it's
already present in m_opened_devices.

Removing the device from m_opened_devices after calling OH0::TriggerHook
in OH0::OnDeviceChange resolves this specific issue in my testing. Doing
this matches us removing the device from m_opened_devices after calling
OH0::TriggerHook in OH0::DeviceClose, but I haven't looked at exactly
what real IOS does.

I have been able to reproduce a much rarer issue that has the same
symptoms on the surface but where OH0::DeviceOpen gets past its
m_opened_devices check. I'm currently not sure what the cause of this
remaining issue is.
This commit is contained in:
JosJuice 2025-04-06 16:50:28 +02:00
parent ac76deaef0
commit bda1f379b7

View file

@ -81,10 +81,10 @@ void OH0::DoState(PointerWrap& p)
5000);
Core::DisplayMessage("If USB doesn't work properly, an emulation reset may be needed.", 5000);
}
}
p.Do(m_insertion_hooks);
p.Do(m_removal_hooks);
p.Do(m_opened_devices);
}
USBHost::DoState(p);
}
@ -243,9 +243,18 @@ bool OH0::HasDeviceWithVidPid(const u16 vid, const u16 pid) const
void OH0::OnDeviceChange(const ChangeEvent event, std::shared_ptr<USB::Device> device)
{
if (event == ChangeEvent::Inserted)
{
TriggerHook(m_insertion_hooks, {device->GetVid(), device->GetPid()}, IPC_SUCCESS);
}
else if (event == ChangeEvent::Removed)
{
TriggerHook(m_removal_hooks, device->GetId(), IPC_SUCCESS);
// This fixes a problem where Rock Band 3 randomly fails to detect reconnected microphones.
// Real IOS behavior untested.
std::lock_guard lk(m_devices_mutex);
m_opened_devices.erase(device->GetId());
}
}
template <typename T>
@ -286,6 +295,7 @@ std::pair<ReturnCode, u64> OH0::DeviceOpen(const u16 vid, const u16 pid)
void OH0::DeviceClose(const u64 device_id)
{
TriggerHook(m_removal_hooks, device_id, IPC_ENOENT);
std::lock_guard lk(m_devices_mutex);
m_opened_devices.erase(device_id);
}