mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-05-07 13:37:46 +00:00
USB: remove zero-length IN URB fake-completion workaround
The passthrough path was fake-completing zero-length bulk/interrupt IN URBs to mirror the emulated path, so games that drain-poll between transfers wouldn't stall the libusb worker thread. This baked an emulator-side assumption about device behaviour into the host stack. Real PS3 USIO devices issue a ZLP on the read endpoint after any transfer that would otherwise leave the host's drain URB outstanding (notably after a CMD_WRITE). Devices that follow the same protocol (e.g. ITAIKO firmware) are expected to do the same; faking it here masks firmware bugs and diverges from real hardware behaviour. Drop the workaround and let libusb submit the URB normally. The IN URB now completes when the device sends its ZLP, matching real PS3. Refs: https://github.com/RPCS3/rpcs3/pull/18636#discussion_r3143290987
This commit is contained in:
parent
771837ee55
commit
6d058586c4
1 changed files with 3 additions and 12 deletions
|
|
@ -188,24 +188,15 @@ void usb_device_passthrough::control_transfer(u8 bmRequestType, u8 bRequest, u16
|
|||
|
||||
void usb_device_passthrough::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, UsbTransfer* transfer)
|
||||
{
|
||||
// Zero-length bulk/interrupt IN URBs hang in libusb until the device sends a ZLP.
|
||||
// The emulated path fake-completes these immediately with count=0; mirror that here
|
||||
// so games that do drain-polls between transfers don't stall the worker thread.
|
||||
if (buf_size == 0 && (endpoint & LIBUSB_ENDPOINT_IN))
|
||||
{
|
||||
transfer->fake = true;
|
||||
transfer->expected_count = 0;
|
||||
transfer->expected_result = HC_CC_NOERR;
|
||||
transfer->expected_time = get_timestamp() + 1'000;
|
||||
return;
|
||||
}
|
||||
|
||||
// Pick the libusb helper matching the endpoint's actual transfer type. The PS3 USB
|
||||
// stack routes both bulk and interrupt transfers through this method, but submitting
|
||||
// an interrupt URB to a bulk endpoint fails with EINVAL on Linux.
|
||||
const UsbDeviceEndpoint* ep_desc = find_endpoint(static_cast<u8>(endpoint));
|
||||
const bool is_bulk = ep_desc && (ep_desc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK;
|
||||
|
||||
sys_usbd.notice("USIO debug: submitting passthrough transfer endpoint=0x%x dir=%s size=0x%x type=%s",
|
||||
endpoint, (endpoint & LIBUSB_ENDPOINT_IN) ? "IN" : "OUT", buf_size, is_bulk ? "bulk" : "interrupt");
|
||||
|
||||
if (is_bulk)
|
||||
{
|
||||
libusb_fill_bulk_transfer(transfer->transfer, lusb_handle, endpoint, buf, buf_size, callback_transfer, transfer, 0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue