mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 09:39:55 +00:00
USB: Added VFS USB mass storage devices to the USB device list
This commit is contained in:
parent
709305df0e
commit
e0fe7989e9
@ -389,6 +389,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||
Io/pad_config_types.cpp
|
||||
Io/PadHandler.cpp
|
||||
Io/usb_device.cpp
|
||||
Io/usb_vfs.cpp
|
||||
Io/Skylander.cpp
|
||||
Io/GHLtar.cpp
|
||||
Io/Buzz.cpp
|
||||
|
@ -3,15 +3,18 @@
|
||||
#include "sys_ppu_thread.h"
|
||||
#include "sys_sync.h"
|
||||
|
||||
#include <charconv>
|
||||
#include <queue>
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/vfs_config.h"
|
||||
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
|
||||
#include "Emu/Io/usb_device.h"
|
||||
#include "Emu/Io/usb_vfs.h"
|
||||
#include "Emu/Io/Skylander.h"
|
||||
#include "Emu/Io/GHLtar.h"
|
||||
#include "Emu/Io/Buzz.h"
|
||||
@ -290,6 +293,34 @@ usb_handler_thread::usb_handler_thread()
|
||||
|
||||
libusb_free_device_list(list, 1);
|
||||
|
||||
for (int i = 0; i < 8; i++) // Add VFS USB mass storage devices (/dev_usbXXX) to the USB device list
|
||||
{
|
||||
const cfg::device_info device = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, fmt::format("/dev_usb%03d", i));
|
||||
|
||||
if (device.path.empty() || device.vid.empty() || device.pid.empty())
|
||||
continue;
|
||||
|
||||
u16 vid{};
|
||||
{
|
||||
auto [ptr, err] = std::from_chars(device.vid.data(), device.vid.data() + device.vid.size(), vid, 16);
|
||||
if (err != std::errc())
|
||||
{
|
||||
fmt::throw_exception("Failed to read hex string: %s", std::make_error_code(err).message());
|
||||
}
|
||||
}
|
||||
|
||||
u16 pid{};
|
||||
{
|
||||
auto [ptr, err] = std::from_chars(device.pid.data(), device.pid.data() + device.pid.size(), pid, 16);
|
||||
if (err != std::errc())
|
||||
{
|
||||
fmt::throw_exception("Failed to read hex string: %s", std::make_error_code(err).message());
|
||||
}
|
||||
}
|
||||
|
||||
usb_devices.push_back(std::make_shared<usb_device_vfs>(get_new_location(), vid, pid, device.serial));
|
||||
}
|
||||
|
||||
if (!found_skylander)
|
||||
{
|
||||
sys_usbd.notice("Adding emulated skylander");
|
||||
|
@ -27,6 +27,12 @@ void usb_device::read_descriptors()
|
||||
{
|
||||
}
|
||||
|
||||
u32 usb_device::get_configuration(u8* buf)
|
||||
{
|
||||
*buf = current_config;
|
||||
return sizeof(u8);
|
||||
}
|
||||
|
||||
bool usb_device::set_configuration(u8 cfg_num)
|
||||
{
|
||||
current_config = cfg_num;
|
||||
@ -123,6 +129,11 @@ void usb_device_passthrough::read_descriptors()
|
||||
}
|
||||
}
|
||||
|
||||
u32 usb_device_passthrough::get_configuration(u8* buf)
|
||||
{
|
||||
return (libusb_get_configuration(lusb_handle, reinterpret_cast<int*>(buf)) == LIBUSB_SUCCESS) ? sizeof(u8) : 0;
|
||||
};
|
||||
|
||||
bool usb_device_passthrough::set_configuration(u8 cfg_num)
|
||||
{
|
||||
usb_device::set_configuration(cfg_num);
|
||||
@ -187,32 +198,85 @@ bool usb_device_emulated::open_device()
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* ptr, u32 /*max_size*/)
|
||||
u32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size)
|
||||
{
|
||||
if (type == USB_DESCRIPTOR_STRING)
|
||||
u32 expected_count = 2;
|
||||
|
||||
if (buf_size < expected_count)
|
||||
{
|
||||
if (index < strings.size())
|
||||
{
|
||||
u8 string_len = ::narrow<u8>(strings[index].size());
|
||||
ptr[0] = (string_len * 2) + 2;
|
||||
ptr[1] = USB_DESCRIPTOR_STRING;
|
||||
for (u32 i = 0; i < string_len; i++)
|
||||
{
|
||||
ptr[2 + (i * 2)] = strings[index].data()[i];
|
||||
ptr[3 + (i * 2)] = 0;
|
||||
}
|
||||
return ptr[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_usbd.error("[Emulated]: Trying to get a descriptor other than string descriptor");
|
||||
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;
|
||||
}
|
||||
|
||||
return -1;
|
||||
buf[0] = expected_count;
|
||||
buf[1] = type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case USB_DESCRIPTOR_DEVICE:
|
||||
{
|
||||
buf[0] = device.bLength;
|
||||
expected_count = std::min(device.bLength, ::narrow<u8>(buf_size));
|
||||
memcpy(buf + 2, device.data, expected_count - 2);
|
||||
break;
|
||||
}
|
||||
case USB_DESCRIPTOR_CONFIG:
|
||||
{
|
||||
if (index < device.subnodes.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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USB_DESCRIPTOR_STRING:
|
||||
{
|
||||
if (index < strings.size() + 1)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
constexpr u8 len = sizeof(u16) + 2;
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8 len = std::min(strings[index - 1].size() * 2 + 2, static_cast<size_t>(0xFF));
|
||||
buf[0] = len;
|
||||
expected_count = std::min(len, ::narrow<u8>(buf_size));
|
||||
for (u32 i = 0; i < expected_count - 2; i++)
|
||||
{
|
||||
buf[i + 2] = i % 2 == 0 ? strings[index - 1].data()[i / 2] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: sys_usbd.error("Unhandled DescriptorType: get_descriptor(type=0x%02x, index=0x%02x, buf=*0x%x, buf_size=0x%x)", type, index, buf, buf_size); break;
|
||||
}
|
||||
|
||||
return expected_count;
|
||||
}
|
||||
|
||||
void usb_device_emulated::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 /*wIndex*/, u16 /*wLength*/, u32 buf_size, u8* /*buf*/, UsbTransfer* transfer)
|
||||
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 u16 device_status = self_powered | remote_wakeup << 1;
|
||||
memcpy(buf, &device_status, expected_count);
|
||||
return expected_count;
|
||||
}
|
||||
|
||||
void usb_device_emulated::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 /*wIndex*/, u16 /*wLength*/, u32 buf_size, u8* buf, UsbTransfer* transfer)
|
||||
{
|
||||
transfer->fake = true;
|
||||
transfer->expected_count = buf_size;
|
||||
@ -221,15 +285,23 @@ void usb_device_emulated::control_transfer(u8 bmRequestType, u8 bRequest, u16 wV
|
||||
|
||||
switch (bmRequestType)
|
||||
{
|
||||
case 0:
|
||||
case LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE:
|
||||
switch (bRequest)
|
||||
{
|
||||
case 0x09: usb_device::set_configuration(::narrow<u8>(wValue)); break;
|
||||
default: sys_usbd.fatal("Unhandled control transfer(0): 0x%x", bRequest); break;
|
||||
case LIBUSB_REQUEST_SET_CONFIGURATION: usb_device::set_configuration(::narrow<u8>(wValue)); break;
|
||||
default: sys_usbd.error("Unhandled control transfer(0x%02x): 0x%02x", bmRequestType, bRequest); break;
|
||||
}
|
||||
break;
|
||||
case 0x80: sys_usbd.todo("Unimplemented control transfer: 0x%x", bmRequestType); break;
|
||||
default: sys_usbd.fatal("Unhandled control transfer: 0x%x", bmRequestType); break;
|
||||
case LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE:
|
||||
switch (bRequest)
|
||||
{
|
||||
case LIBUSB_REQUEST_GET_STATUS: transfer->expected_count = get_status(false, false, buf, buf_size); break;
|
||||
case LIBUSB_REQUEST_GET_DESCRIPTOR: transfer->expected_count = get_descriptor(wValue >> 8, wValue & 0xFF, buf, buf_size); break;
|
||||
case LIBUSB_REQUEST_GET_CONFIGURATION: transfer->expected_count = get_configuration(buf); break;
|
||||
default: sys_usbd.error("Unhandled control transfer(0x%02x): 0x%02x", bmRequestType, bRequest); break;
|
||||
}
|
||||
break;
|
||||
default: sys_usbd.error("Unhandled control transfer: 0x%02x", bmRequestType); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,6 +177,7 @@ public:
|
||||
void get_location(u8* location) const;
|
||||
virtual void read_descriptors();
|
||||
|
||||
virtual u32 get_configuration(u8* buf);
|
||||
virtual bool set_configuration(u8 cfg_num);
|
||||
virtual bool set_interface(u8 int_num);
|
||||
|
||||
@ -207,6 +208,7 @@ public:
|
||||
|
||||
bool open_device() override;
|
||||
void read_descriptors() override;
|
||||
u32 get_configuration(u8* buf) override;
|
||||
bool set_configuration(u8 cfg_num) override;
|
||||
bool set_interface(u8 int_num) override;
|
||||
void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override;
|
||||
@ -234,7 +236,8 @@ public:
|
||||
|
||||
// Emulated specific functions
|
||||
void add_string(char* str);
|
||||
s32 get_descriptor(u8 type, u8 index, u8* ptr, u32 max_size);
|
||||
u32 get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size);
|
||||
u32 get_status(bool self_powered, bool remote_wakeup, u8* buf, u32 buf_size);
|
||||
|
||||
protected:
|
||||
std::vector<std::string> strings;
|
||||
|
62
rpcs3/Emu/Io/usb_vfs.cpp
Normal file
62
rpcs3/Emu/Io/usb_vfs.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "stdafx.h"
|
||||
#include "usb_vfs.h"
|
||||
|
||||
LOG_CHANNEL(usb_vfs);
|
||||
|
||||
usb_device_vfs::usb_device_vfs(const std::array<u8, 7>& location, const u16 vid, const u16 pid, const std::string& serial)
|
||||
: usb_device_emulated(location)
|
||||
{
|
||||
device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE,
|
||||
UsbDeviceDescriptor{
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = 0x40,
|
||||
.idVendor = vid,
|
||||
.idProduct = pid,
|
||||
.bcdDevice = pid,
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
.bNumConfigurations = 0x01});
|
||||
|
||||
auto& config0 = device.add_node(UsbDescriptorNode(USB_DESCRIPTOR_CONFIG,
|
||||
UsbDeviceConfiguration{
|
||||
.wTotalLength = 0x0020,
|
||||
.bNumInterfaces = 0x01,
|
||||
.bConfigurationValue = 0x01,
|
||||
.iConfiguration = 0x00,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32}));
|
||||
|
||||
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_INTERFACE,
|
||||
UsbDeviceInterface{
|
||||
.bInterfaceNumber = 0x00,
|
||||
.bAlternateSetting = 0x00,
|
||||
.bNumEndpoints = 0x02,
|
||||
.bInterfaceClass = 0x08,
|
||||
.bInterfaceSubClass = 0x06,
|
||||
.bInterfaceProtocol = 0x50,
|
||||
.iInterface = 0x00}));
|
||||
|
||||
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_ENDPOINT,
|
||||
UsbDeviceEndpoint{
|
||||
.bEndpointAddress = 0x81,
|
||||
.bmAttributes = 0x02,
|
||||
.wMaxPacketSize = 0x0200,
|
||||
.bInterval = 0xFF}));
|
||||
|
||||
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_ENDPOINT,
|
||||
UsbDeviceEndpoint{
|
||||
.bEndpointAddress = 0x02,
|
||||
.bmAttributes = 0x02,
|
||||
.wMaxPacketSize = 0x0200,
|
||||
.bInterval = 0xFF}));
|
||||
|
||||
strings = {"SMI Corporation", "USB DISK", serial}; // Manufacturer, Product, SerialNumber
|
||||
}
|
||||
|
||||
usb_device_vfs::~usb_device_vfs()
|
||||
{
|
||||
}
|
10
rpcs3/Emu/Io/usb_vfs.h
Normal file
10
rpcs3/Emu/Io/usb_vfs.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Io/usb_device.h"
|
||||
|
||||
class usb_device_vfs : public usb_device_emulated
|
||||
{
|
||||
public:
|
||||
usb_device_vfs(const std::array<u8, 7>& location, const u16 vid, const u16 pid, const std::string& serial);
|
||||
~usb_device_vfs();
|
||||
};
|
@ -370,6 +370,7 @@
|
||||
<ClCompile Include="Emu\IdManager.cpp" />
|
||||
<ClCompile Include="Emu\Io\Skylander.cpp" />
|
||||
<ClCompile Include="Emu\Io\usb_device.cpp" />
|
||||
<ClCompile Include="Emu\Io\usb_vfs.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Capture\rsx_capture.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Capture\rsx_replay.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Program\CgBinaryFragmentProgram.cpp" />
|
||||
@ -641,6 +642,7 @@
|
||||
<ClInclude Include="Emu\CPU\CPUTranslator.h" />
|
||||
<ClInclude Include="Emu\Io\Skylander.h" />
|
||||
<ClInclude Include="Emu\Io\usb_device.h" />
|
||||
<ClInclude Include="Emu\Io\usb_vfs.h" />
|
||||
<ClInclude Include="Emu\IPC.h" />
|
||||
<ClInclude Include="Emu\Audio\AudioDumper.h" />
|
||||
<ClInclude Include="Emu\Audio\AudioBackend.h" />
|
||||
|
@ -870,6 +870,9 @@
|
||||
<ClCompile Include="Emu\Io\usb_device.cpp">
|
||||
<Filter>Emu\Io</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="Emu\Io\usb_vfs.cpp">
|
||||
<Filter>Emu\Io</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\atomic.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
@ -1851,6 +1854,9 @@
|
||||
<ClInclude Include="Emu\Io\usb_device.h">
|
||||
<Filter>Emu\Io</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\Io\usb_vfs.h">
|
||||
<Filter>Emu\Io</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="Crypto\aesni.h">
|
||||
<Filter>Crypto</Filter>
|
||||
</ClInclude>
|
||||
|
Loading…
x
Reference in New Issue
Block a user