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); } }