1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-01-31 12:31:45 +01:00

sys_usbd: Fix up sys_usbd_get_descriptor() error handling according to hardware test

usb_device_emulated: Allow partial copy of desscriptors
This commit is contained in:
brian218 2023-12-18 00:49:42 +08:00 committed by Elad Ashkenazi
parent d18f929faf
commit 19d1e4dcc9
2 changed files with 20 additions and 24 deletions

View File

@ -850,6 +850,11 @@ error_code sys_usbd_get_descriptor(ppu_thread& ppu, u32 handle, u32 device_handl
sys_usbd.trace("sys_usbd_get_descriptor(handle=0x%x, deviceNumber=0x%x, descriptor=0x%x, desc_size=0x%x)", handle, device_handle, descriptor, desc_size);
if (!descriptor)
{
return CELL_EINVAL;
}
auto& usbh = g_fxo->get<named_thread<usb_handler_thread>>();
std::lock_guard lock(usbh.mutex);
@ -859,9 +864,9 @@ error_code sys_usbd_get_descriptor(ppu_thread& ppu, u32 handle, u32 device_handl
return CELL_EINVAL;
}
if (!descriptor)
if (!desc_size)
{
return CELL_EFAULT;
return CELL_ENOMEM;
}
usbh.handled_devices[device_handle].second->device.write_data(reinterpret_cast<u8*>(descriptor.get_ptr()), desc_size);

View File

@ -200,16 +200,14 @@ bool usb_device_emulated::open_device()
u32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size)
{
u32 expected_count = 2;
std::array<u8, 2> header;
header = {header.size(), type};
if (buf_size < expected_count)
{
sys_usbd.error("Illegal buf_size: get_descriptor(type=0x%02x, index=0x%02x, buf=*0x%x, buf_size=0x%x)", type, index, buf, buf_size);
return 0;
}
u32 expected_count = buf ? std::min<u32>(header.size(), buf_size) : 0;
memcpy(buf, header.data(), expected_count);
buf[0] = expected_count;
buf[1] = type;
if (expected_count < header.size())
return expected_count;
switch (type)
{
@ -217,7 +215,7 @@ u32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size
{
buf[0] = device.bLength;
expected_count = std::min(device.bLength, ::narrow<u8>(buf_size));
memcpy(buf + 2, device.data, expected_count - 2);
memcpy(buf + header.size(), device.data, expected_count - header.size());
break;
}
case USB_DESCRIPTOR_CONFIG:
@ -226,7 +224,7 @@ u32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size
{
buf[0] = device.subnodes[index].bLength;
expected_count = std::min(device.subnodes[index].bLength, ::narrow<u8>(buf_size));
memcpy(buf + 2, device.subnodes[index].data, expected_count - 2);
memcpy(buf + header.size(), device.subnodes[index].data, expected_count - header.size());
}
break;
}
@ -236,19 +234,19 @@ u32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size
{
if (index == 0)
{
constexpr u8 len = sizeof(u16) + 2;
constexpr u8 len = sizeof(u16) + header.size();
buf[0] = len;
expected_count = std::min(len, ::narrow<u8>(buf_size));
constexpr le_t<u16> langid = 0x0409; // English (United States)
memcpy(buf + 2, &langid, expected_count - 2);
memcpy(buf + header.size(), &langid, expected_count - header.size());
}
else
{
const std::u16string u16str = utf8_to_utf16(strings[index - 1]);
const u8 len = static_cast<u8>(std::min(u16str.size() * sizeof(u16) + 2, static_cast<usz>(0xFF)));
const u8 len = static_cast<u8>(std::min(u16str.size() * sizeof(u16) + header.size(), static_cast<usz>(0xFF)));
buf[0] = len;
expected_count = std::min(len, ::narrow<u8>(std::min<u32>(255, buf_size)));
memcpy(buf + 2, u16str.data(), expected_count - 2);
memcpy(buf + header.size(), u16str.data(), expected_count - header.size());
}
}
break;
@ -261,14 +259,7 @@ u32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size
u32 usb_device_emulated::get_status(bool self_powered, bool remote_wakeup, u8* buf, u32 buf_size)
{
constexpr u32 expected_count = sizeof(u16);
if (buf_size < expected_count)
{
sys_usbd.error("Illegal buf_size: get_status(self_powered=0x%02x, remote_wakeup=0x%02x, buf=*0x%x, buf_size=0x%x)", self_powered, remote_wakeup, buf, buf_size);
return 0;
}
const u32 expected_count = buf ? std::min<u32>(sizeof(u16), buf_size) : 0;
const u16 device_status = static_cast<int>(self_powered) | static_cast<int>(remote_wakeup) << 1;
memcpy(buf, &device_status, expected_count);
return expected_count;