From d2dc57585c85f1dd068ab0a617272f93f6e22ba8 Mon Sep 17 00:00:00 2001 From: brian218 Date: Wed, 18 Jan 2023 10:22:21 +0800 Subject: [PATCH] sys_fs: Improved sys_fs_fcntl(0xc0000015&0xc000001c) --- Utilities/Config.cpp | 12 ++++++ Utilities/Config.h | 1 + Utilities/StrFmt.cpp | 6 +++ Utilities/StrUtil.h | 1 + rpcs3/Emu/Cell/lv2/sys_fs.cpp | 73 ++------------------------------- rpcs3/Emu/Cell/lv2/sys_fs.h | 2 +- rpcs3/Emu/Cell/lv2/sys_usbd.cpp | 26 +----------- rpcs3/Emu/Io/usb_device.cpp | 10 ++--- rpcs3/Emu/Io/usb_vfs.cpp | 6 ++- rpcs3/Emu/Io/usb_vfs.h | 3 +- 10 files changed, 36 insertions(+), 104 deletions(-) diff --git a/Utilities/Config.cpp b/Utilities/Config.cpp index 05977d4e0f..4f0b0e31be 100644 --- a/Utilities/Config.cpp +++ b/Utilities/Config.cpp @@ -559,6 +559,18 @@ void cfg::log_entry::from_default() set_map({}); } +std::pair cfg::device_info::get_usb_ids() const +{ + auto string_to_hex = [](const std::string& str) -> u16 + { + u16 value = 0x0000; + if (!str.empty() && std::from_chars(str.data(), str.data() + str.size(), value, 16).ec != std::errc{}) + cfg_log.error("Failed to parse hex from string \"%s\"", str); + return value; + }; + return {string_to_hex(vid), string_to_hex(pid)}; +} + void cfg::device_entry::set_map(map_of_type&& map) { m_map = std::move(map); diff --git a/Utilities/Config.h b/Utilities/Config.h index d5f530fea3..a3f3f1354e 100644 --- a/Utilities/Config.h +++ b/Utilities/Config.h @@ -644,6 +644,7 @@ namespace cfg std::string serial; std::string vid; std::string pid; + std::pair get_usb_ids() const; }; class device_entry final : public _base diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index b9a2084095..8244ca3e19 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -37,6 +37,12 @@ std::string utf16_to_utf8(std::u16string_view src) return converter.to_bytes(src.data()); } +std::u16string utf8_to_utf16(std::string_view src) +{ + std::wstring_convert, char16_t> converter{}; + return converter.from_bytes(src.data()); +} + std::wstring utf8_to_wchar(std::string_view src) { #ifdef _WIN32 diff --git a/Utilities/StrUtil.h b/Utilities/StrUtil.h index 432f18d924..da64fafa35 100644 --- a/Utilities/StrUtil.h +++ b/Utilities/StrUtil.h @@ -11,6 +11,7 @@ std::wstring utf8_to_wchar(std::string_view src); std::string wchar_to_utf8(std::wstring_view src); std::string utf16_to_utf8(std::u16string_view src); +std::u16string utf8_to_utf16(std::string_view src); // Copy null-terminated string from a std::string or a char array to a char array with truncation template diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 0c4c0113d2..3f8aae22d2 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -12,10 +12,8 @@ #include "Emu/IdManager.h" #include "Emu/system_utils.hpp" #include "Emu/Cell/lv2/sys_process.h" -#include "Emu/RSX/Overlays/overlay_utils.h" // for ascii8_to_utf16 #include "Utilities/StrUtil.h" -#include #include LOG_CHANNEL(sys_fs); @@ -2117,33 +2115,8 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr _arg, u32 } const cfg::device_info device = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, vpath); + std::tie(arg->vendorID, arg->productID) = device.get_usb_ids(); - if (device.path.empty() || device.vid.empty() || device.pid.empty()) - { - arg->out_code = CELL_ENOTSUP; - break; - } - - 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()); - } - } - - arg->vendorID = vid; - arg->productID = pid; arg->out_code = CELL_OK; sys_fs.trace("sys_fs_fcntl(0xc0000015): found device '%s' (vid=0x%x, pid=0x%x)", vpath, arg->vendorID, arg->productID); @@ -2192,49 +2165,11 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr _arg, u32 } const cfg::device_info device = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, vpath); - - if (device.path.empty() || device.vid.empty() || device.pid.empty()) - { - arg->out_code = CELL_ENOTSUP; - break; - } - - 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()); - } - } - - arg->vendorID = vid; - arg->productID = pid; + std::tie(arg->vendorID, arg->productID) = device.get_usb_ids(); // Serial needs to be encoded to utf-16 BE - const std::u16string serial = ascii8_to_utf16(device.serial); - ensure((serial.size() * sizeof(u16)) <= sizeof(arg->serial)); - - std::memset(arg->serial, 0, sizeof(arg->serial)); - - const auto write_byteswapped = [](const void* src, void* dst) -> void - { - *static_cast(dst) = *static_cast*>(src); - }; - - for (size_t i = 0; i < serial.size(); i++) - { - write_byteswapped(&serial[i], &arg->serial[i * 2]); - } + const std::u16string serial = utf8_to_utf16(device.serial); + std::copy_n(serial.begin(), std::min(serial.size(), sizeof(arg->serial) / sizeof(u16)), arg->serial); arg->out_code = CELL_OK; diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index f1af975b3d..ffc692f26e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -533,7 +533,7 @@ struct lv2_file_c000001c : lv2_file_op be_t vendorID; be_t productID; be_t out_code; // set to 0 - u8 serial[64]; + be_t serial[32]; }; CHECK_SIZE(lv2_file_c000001c, 0x60); diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index d18635bbdc..0726d96e3f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -3,7 +3,6 @@ #include "sys_ppu_thread.h" #include "sys_sync.h" -#include #include #include "Emu/System.h" #include "Emu/Memory/vm.h" @@ -295,30 +294,7 @@ usb_handler_thread::usb_handler_thread() 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(get_new_location(), vid, pid, device.serial)); + usb_devices.push_back(std::make_shared(g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, fmt::format("/dev_usb%03d", i)), get_new_location())); } if (!found_skylander) diff --git a/rpcs3/Emu/Io/usb_device.cpp b/rpcs3/Emu/Io/usb_device.cpp index 8a324494d9..e7074c6a6b 100644 --- a/rpcs3/Emu/Io/usb_device.cpp +++ b/rpcs3/Emu/Io/usb_device.cpp @@ -1,8 +1,8 @@ #include "stdafx.h" #include "Emu/System.h" - #include "Emu/Cell/lv2/sys_usbd.h" #include "Emu/Io/usb_device.h" +#include "Utilities/StrUtil.h" #include LOG_CHANNEL(sys_usbd); @@ -244,13 +244,11 @@ u32 usb_device_emulated::get_descriptor(u8 type, u8 index, u8* buf, u32 buf_size } else { - const u8 len = std::min(strings[index - 1].size() * 2 + 2, static_cast(0xFF)); + const std::u16string u16str = utf8_to_utf16(strings[index - 1]); + const u8 len = std::min(u16str.size() * sizeof(u16) + 2, static_cast(0xFF)); buf[0] = len; expected_count = std::min(len, ::narrow(buf_size)); - for (u32 i = 0; i < expected_count - 2; i++) - { - buf[i + 2] = i % 2 == 0 ? strings[index - 1].data()[i / 2] : 0; - } + memcpy(buf + 2, u16str.data(), expected_count - 2); } } break; diff --git a/rpcs3/Emu/Io/usb_vfs.cpp b/rpcs3/Emu/Io/usb_vfs.cpp index c0a7f5c38f..cea02fb276 100644 --- a/rpcs3/Emu/Io/usb_vfs.cpp +++ b/rpcs3/Emu/Io/usb_vfs.cpp @@ -3,9 +3,11 @@ LOG_CHANNEL(usb_vfs); -usb_device_vfs::usb_device_vfs(const std::array& location, const u16 vid, const u16 pid, const std::string& serial) +usb_device_vfs::usb_device_vfs(const cfg::device_info& device_info, const std::array& location) : usb_device_emulated(location) { + const auto [vid, pid] = device_info.get_usb_ids(); + device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{ .bcdUSB = 0x0200, @@ -54,7 +56,7 @@ usb_device_vfs::usb_device_vfs(const std::array& location, const u16 vid, .wMaxPacketSize = 0x0200, .bInterval = 0xFF})); - strings = {"SMI Corporation", "USB DISK", serial}; // Manufacturer, Product, SerialNumber + strings = {"SMI Corporation", "USB DISK", device_info.serial}; // Manufacturer, Product, SerialNumber } usb_device_vfs::~usb_device_vfs() diff --git a/rpcs3/Emu/Io/usb_vfs.h b/rpcs3/Emu/Io/usb_vfs.h index a5c9faa517..ad734d368d 100644 --- a/rpcs3/Emu/Io/usb_vfs.h +++ b/rpcs3/Emu/Io/usb_vfs.h @@ -1,10 +1,11 @@ #pragma once #include "Emu/Io/usb_device.h" +#include "Utilities/Config.h" class usb_device_vfs : public usb_device_emulated { public: - usb_device_vfs(const std::array& location, const u16 vid, const u16 pid, const std::string& serial); + usb_device_vfs(const cfg::device_info& device_info, const std::array& location); ~usb_device_vfs(); };