From e4ea4da78215918371ad85a798d20de4d81e7f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 19 Aug 2017 15:55:10 +0200 Subject: [PATCH] IOS: Check for available features when adding devices Prevents resource managers that shouldn't be visible from being exposed to titles. This adds a new function to get features for an IOS version, and also moves the version checks from the modules themselves to VersionInfo. This hopefully documents some of the differences between IOS better and should be slightly cleaner than having random version checks. --- Source/Core/Core/IOS/IOS.cpp | 70 +++++++++++++++++----- Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp | 23 +------ Source/Core/Core/IOS/USB/OH0/OH0.cpp | 4 +- Source/Core/Core/IOS/USB/OH0/OH0Device.cpp | 4 -- Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp | 8 --- Source/Core/Core/IOS/USB/USB_VEN/VEN.h | 1 - Source/Core/Core/IOS/VersionInfo.cpp | 39 ++++++++++++ Source/Core/Core/IOS/VersionInfo.h | 46 ++++++++++++++ 8 files changed, 143 insertions(+), 52 deletions(-) diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 464093018c..d782c3f5b6 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -345,32 +345,69 @@ void Kernel::AddStaticDevices() { std::lock_guard lock(m_device_map_mutex); + const Feature features = GetFeatures(GetVersion()); + + // OH1 (Bluetooth) + AddDevice(std::make_unique(*this, "/dev/usb/oh1")); if (!SConfig::GetInstance().m_bt_passthrough_enabled) AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); else AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); + // Other core modules AddDevice(std::make_unique(*this, "/dev/stm/immediate")); AddDevice(std::make_unique(*this, "/dev/stm/eventhook")); AddDevice(std::make_unique(*this, "/dev/di")); - AddDevice(std::make_unique(*this, "/dev/net/kd/request")); - AddDevice(std::make_unique(*this, "/dev/net/kd/time")); - AddDevice(std::make_unique(*this, "/dev/net/ncd/manage")); - AddDevice(std::make_unique(*this, "/dev/net/wd/command")); - AddDevice(std::make_unique(*this, "/dev/net/ip/top")); - AddDevice(std::make_unique(*this, "/dev/net/ssl")); - AddDevice(std::make_unique(*this, "/dev/usb/kbd")); AddDevice(std::make_unique(*this, "/dev/sdio/slot0")); AddDevice(std::make_unique(*this, "/dev/sdio/slot1")); - if (GetVersion() == 59) - AddDevice(std::make_unique(*this, "/dev/usb/hid")); - else - AddDevice(std::make_unique(*this, "/dev/usb/hid")); + + // Network modules + if (HasFeature(features, Feature::KD)) + { + AddDevice(std::make_unique(*this, "/dev/net/kd/request")); + AddDevice(std::make_unique(*this, "/dev/net/kd/time")); + } + if (HasFeature(features, Feature::NCD)) + { + AddDevice(std::make_unique(*this, "/dev/net/ncd/manage")); + } + if (HasFeature(features, Feature::WiFi)) + { + AddDevice(std::make_unique(*this, "/dev/net/wd/command")); + } + if (HasFeature(features, Feature::SO)) + { + AddDevice(std::make_unique(*this, "/dev/net/ip/top")); + } + if (HasFeature(features, Feature::SSL)) + { + AddDevice(std::make_unique(*this, "/dev/net/ssl")); + } + + // USB modules + // OH0 is unconditionally added because this device path is registered in all cases. AddDevice(std::make_unique(*this, "/dev/usb/oh0")); - AddDevice(std::make_unique(*this, "/dev/usb/oh1")); - AddDevice(std::make_unique(*this, "/dev/usb/ven")); - AddDevice(std::make_unique(*this, "/dev/usb/wfssrv")); - AddDevice(std::make_unique(*this, "/dev/wfsi")); + if (HasFeature(features, Feature::NewUSB)) + { + AddDevice(std::make_unique(*this, "/dev/usb/hid")); + AddDevice(std::make_unique(*this, "/dev/usb/ven")); + + // TODO(IOS): register /dev/usb/usb, /dev/usb/msc, /dev/usb/hub and /dev/usb/ehc + // as stubs that return IPC_EACCES. + } + else + { + if (HasFeature(features, Feature::USB_HIDv4)) + AddDevice(std::make_unique(*this, "/dev/usb/hid")); + if (HasFeature(features, Feature::USB_KBD)) + AddDevice(std::make_unique(*this, "/dev/usb/kbd")); + } + + if (HasFeature(features, Feature::WFS)) + { + AddDevice(std::make_unique(*this, "/dev/usb/wfssrv")); + AddDevice(std::make_unique(*this, "/dev/wfsi")); + } } s32 Kernel::GetFreeDeviceID() @@ -411,7 +448,8 @@ s32 Kernel::OpenDevice(OpenRequest& request) request.fd = new_fd; std::shared_ptr device; - if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path)) + if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path) && + !HasFeature(GetVersion(), Feature::NewUSB)) { device = std::make_shared(*this, request.path); } diff --git a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp index a832c66b38..362d6284dc 100644 --- a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp +++ b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp @@ -18,6 +18,7 @@ #include "Core/ConfigManager.h" #include "Core/HW/Memmap.h" #include "Core/IOS/IOS.h" +#include "Core/IOS/VersionInfo.h" namespace IOS { @@ -25,28 +26,8 @@ namespace HLE { namespace Device { -constexpr bool SupportsSDHC(u32 ios_version) -{ - switch (ios_version) - { - // Known versions to support SDHC - case 48: - case 56: - case 57: - case 58: - case 59: - case 60: - case 61: - case 70: - case 80: - return true; - default: - return false; - }; -} - SDIOSlot0::SDIOSlot0(Kernel& ios, const std::string& device_name) - : Device(ios, device_name), m_sdhc_supported(SupportsSDHC(ios.GetVersion())) + : Device(ios, device_name), m_sdhc_supported(HasFeature(ios.GetVersion(), Feature::SDv2)) { } diff --git a/Source/Core/Core/IOS/USB/OH0/OH0.cpp b/Source/Core/Core/IOS/USB/OH0/OH0.cpp index 85760299bd..3b574bcc5c 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0.cpp @@ -18,6 +18,7 @@ #include "Core/HW/Memmap.h" #include "Core/IOS/USB/Common.h" #include "Core/IOS/USB/USBV0.h" +#include "Core/IOS/VersionInfo.h" namespace IOS { @@ -36,8 +37,7 @@ OH0::~OH0() ReturnCode OH0::Open(const OpenRequest& request) { - const u32 ios_major_version = m_ios.GetVersion(); - if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59) + if (HasFeature(m_ios.GetVersion(), Feature::NewUSB)) return IPC_EACCES; return USBHost::Open(request); } diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp index ab1cafc25b..0b8c56d0ea 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp @@ -57,10 +57,6 @@ void OH0Device::DoState(PointerWrap& p) ReturnCode OH0Device::Open(const OpenRequest& request) { - const u32 ios_major_version = m_ios.GetVersion(); - if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59) - return IPC_ENOENT; - if (m_vid == 0 && m_pid == 0) return IPC_ENOENT; diff --git a/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp b/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp index 955710f176..e2a327a7b7 100644 --- a/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp +++ b/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp @@ -35,14 +35,6 @@ USB_VEN::~USB_VEN() StopThreads(); } -ReturnCode USB_VEN::Open(const OpenRequest& request) -{ - const u32 ios_major_version = m_ios.GetVersion(); - if (ios_major_version != 57 && ios_major_version != 58 && ios_major_version != 59) - return IPC_ENOENT; - return USBHost::Open(request); -} - IPCCommandResult USB_VEN::IOCtl(const IOCtlRequest& request) { request.Log(GetDeviceName(), LogTypes::IOS_USB); diff --git a/Source/Core/Core/IOS/USB/USB_VEN/VEN.h b/Source/Core/Core/IOS/USB/USB_VEN/VEN.h index ed8d71a8d7..dc128d01f9 100644 --- a/Source/Core/Core/IOS/USB/USB_VEN/VEN.h +++ b/Source/Core/Core/IOS/USB/USB_VEN/VEN.h @@ -31,7 +31,6 @@ public: USB_VEN(Kernel& ios, const std::string& device_name); ~USB_VEN() override; - ReturnCode Open(const OpenRequest& request) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; diff --git a/Source/Core/Core/IOS/VersionInfo.cpp b/Source/Core/Core/IOS/VersionInfo.cpp index 8008998be7..38e4eb003e 100644 --- a/Source/Core/Core/IOS/VersionInfo.cpp +++ b/Source/Core/Core/IOS/VersionInfo.cpp @@ -335,5 +335,44 @@ const std::array& GetMemoryValues() { return ios_memory_values; } + +Feature GetFeatures(u32 version) +{ + // Common features that are present in most versions. + Feature features = Feature::Core | Feature::SDIO | Feature::SO | Feature::Ethernet; + + // IOS4 is a tiny IOS that was presumably used during manufacturing. It lacks network support. + if (version != 4) + features |= Feature::KD | Feature::SSL | Feature::NCD | Feature::WiFi; + + if (version == 48 || (version >= 56 && version <= 62) || version == 70 || version == 80) + features |= Feature::SDv2; + + if (version == 57 || version == 58 || version == 59) + features |= Feature::NewUSB; + if (version == 58 || version == 59) + features |= Feature::EHCI; + if (version == 59) + features |= Feature::WFS; + + // No IOS earlier than IOS30 has USB_KBD. Any IOS with the new USB modules lacks this module. + // TODO(IOS): it is currently unknown which other versions don't have it. + if (version >= 30 && !HasFeature(features, Feature::NewUSB)) + features |= Feature::USB_KBD; + + // Just like KBD, USB_HIDv4 is not present on any IOS with the new USB modules + // (since it's been replaced with USB_HIDv5 there). + // Additionally, it appears that HIDv4 and KBD are never both present. + // TODO(IOS): figure out which versions have HIDv4. For now we just include both KBD and HIDv4. + if (!HasFeature(features, Feature::NewUSB)) + features |= Feature::USB_HIDv4; + + return features; +} + +bool HasFeature(u32 major_version, Feature feature) +{ + return HasFeature(GetFeatures(major_version), feature); +} } } diff --git a/Source/Core/Core/IOS/VersionInfo.h b/Source/Core/Core/IOS/VersionInfo.h index d04dedd9c5..1b64b8b2aa 100644 --- a/Source/Core/Core/IOS/VersionInfo.h +++ b/Source/Core/Core/IOS/VersionInfo.h @@ -37,5 +37,51 @@ struct MemoryValues }; const std::array& GetMemoryValues(); + +enum class Feature +{ + // Kernel, ES, FS, STM, DI, OH0, OH1 + Core = 1 << 0, + // SDIO + SDIO = 1 << 1, + // Network (base support: SO, Ethernet; KD, SSL, NCD, Wi-Fi) + SO = 1 << 2, + Ethernet = 1 << 3, + KD = 1 << 4, + SSL = 1 << 5, + NCD = 1 << 6, + WiFi = 1 << 7, + // KBD + USB_KBD = 1 << 8, + // USB_HID v4 + USB_HIDv4 = 1 << 9, + // SDv2 support + SDv2 = 1 << 10, + // New USB modules (USB, USB_VEN, USB_HUB, USB_MSC, OHCI0, USB_HIDv5) + NewUSB = 1 << 11, + // EHCI + EHCI = 1 << 12, + // WFS (WFSSRV, WFSI, USB_SHARED) + WFS = 1 << 13, +}; + +constexpr Feature operator|(Feature lhs, Feature rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +constexpr Feature& operator|=(Feature& lhs, Feature rhs) +{ + lhs = lhs | rhs; + return lhs; +} + +constexpr bool HasFeature(Feature features, Feature feature) +{ + return (static_cast(features) & static_cast(feature)) != 0; +} + +bool HasFeature(u32 major_version, Feature feature); +Feature GetFeatures(u32 major_version); } }