diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index b66ffc856b..1da032f913 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -30,7 +30,9 @@ void fmt_class_string::format(std::string& out, u64 arg) std::string datrace; const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - for (int index = 0; index < transfer.actual_length; index++) + const int data_start = transfer.type == LIBUSB_TRANSFER_TYPE_CONTROL ? LIBUSB_CONTROL_SETUP_SIZE : 0; + + for (int index = data_start; index < data_start + transfer.actual_length; index++) { datrace += hex[transfer.buffer[index] >> 4]; datrace += hex[(transfer.buffer[index]) & 15]; @@ -418,6 +420,12 @@ void usb_handler_thread::transfer_complete(struct libusb_transfer* transfer) usbd_transfer->iso_request.packets[index] = ((iso_status & 0xF) << 12 | (transfer->iso_packet_desc[index].actual_length & 0xFFF)); } + if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL && usbd_transfer->control_destbuf) + { + memcpy(usbd_transfer->control_destbuf, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer->actual_length); + usbd_transfer->control_destbuf = nullptr; + } + usbd_transfer->busy = false; send_message(SYS_USBD_TRANSFER_COMPLETE, usbd_transfer->transfer_id); diff --git a/rpcs3/Emu/Io/usb_device.cpp b/rpcs3/Emu/Io/usb_device.cpp index 5043b17642..42d8dc3347 100644 --- a/rpcs3/Emu/Io/usb_device.cpp +++ b/rpcs3/Emu/Io/usb_device.cpp @@ -135,13 +135,15 @@ bool usb_device_passthrough::set_interface(u8 int_num) return (libusb_claim_interface(lusb_handle, int_num) == LIBUSB_SUCCESS); } -void usb_device_passthrough::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 /*wLength*/, u32 buf_size, u8* buf, UsbTransfer* transfer) +void usb_device_passthrough::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, [[maybe_unused]] u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) { - if (transfer->setup_buf.size() < buf_size + 8) - transfer->setup_buf.resize(buf_size + 8); + if (transfer->setup_buf.size() < buf_size + LIBUSB_CONTROL_SETUP_SIZE) + transfer->setup_buf.resize(buf_size + LIBUSB_CONTROL_SETUP_SIZE); + + transfer->control_destbuf = (bmRequestType & LIBUSB_ENDPOINT_IN) ? buf : nullptr; libusb_fill_control_setup(transfer->setup_buf.data(), bmRequestType, bRequest, wValue, wIndex, buf_size); - memcpy(transfer->setup_buf.data() + 8, buf, buf_size); + memcpy(transfer->setup_buf.data() + LIBUSB_CONTROL_SETUP_SIZE, buf, buf_size); libusb_fill_control_transfer(transfer->transfer, lusb_handle, transfer->setup_buf.data(), callback_transfer, transfer, 0); send_libusb_transfer(transfer->transfer); } diff --git a/rpcs3/Emu/Io/usb_device.h b/rpcs3/Emu/Io/usb_device.h index a665f01dd5..3220d1c4c2 100644 --- a/rpcs3/Emu/Io/usb_device.h +++ b/rpcs3/Emu/Io/usb_device.h @@ -98,6 +98,9 @@ struct UsbTransfer libusb_transfer* transfer = nullptr; bool busy = false; + // For control transfers + u8 *control_destbuf = nullptr; + // For fake transfers bool fake = false; u64 expected_time = 0;