diff --git a/Source/Core/Core/IOS/Device.cpp b/Source/Core/Core/IOS/Device.cpp index 5d38c7efff..e407d54777 100644 --- a/Source/Core/Core/IOS/Device.cpp +++ b/Source/Core/Core/IOS/Device.cpp @@ -154,9 +154,10 @@ ReturnCode Device::Open(const OpenRequest& request) return IPC_SUCCESS; } -void Device::Close() +ReturnCode Device::Close(u32 fd) { m_is_active = false; + return IPC_SUCCESS; } IPCCommandResult Device::Unsupported(const Request& request) diff --git a/Source/Core/Core/IOS/Device.h b/Source/Core/Core/IOS/Device.h index 91d2dbbe36..c8dd0ccf30 100644 --- a/Source/Core/Core/IOS/Device.h +++ b/Source/Core/Core/IOS/Device.h @@ -185,7 +185,7 @@ public: // Replies to Open and Close requests are sent by the IPC request handler (HandleCommand), // not by the devices themselves. virtual ReturnCode Open(const OpenRequest& request); - virtual void Close(); + virtual ReturnCode Close(u32 fd); virtual IPCCommandResult Seek(const SeekRequest& seek) { return Unsupported(seek); } virtual IPCCommandResult Read(const ReadWriteRequest& read) { return Unsupported(read); } virtual IPCCommandResult Write(const ReadWriteRequest& write) { return Unsupported(write); } diff --git a/Source/Core/Core/IOS/DeviceStub.cpp b/Source/Core/Core/IOS/DeviceStub.cpp index cdd74ac1bc..2502c84769 100644 --- a/Source/Core/Core/IOS/DeviceStub.cpp +++ b/Source/Core/Core/IOS/DeviceStub.cpp @@ -22,12 +22,6 @@ ReturnCode Stub::Open(const OpenRequest& request) return IPC_SUCCESS; } -void Stub::Close() -{ - WARN_LOG(IOS, "%s faking Close()", m_name.c_str()); - m_is_active = false; -} - IPCCommandResult Stub::IOCtl(const IOCtlRequest& request) { WARN_LOG(IOS, "%s faking IOCtl()", m_name.c_str()); diff --git a/Source/Core/Core/IOS/DeviceStub.h b/Source/Core/Core/IOS/DeviceStub.h index 6b7298cc53..b6b60b0248 100644 --- a/Source/Core/Core/IOS/DeviceStub.h +++ b/Source/Core/Core/IOS/DeviceStub.h @@ -22,7 +22,6 @@ public: Stub(u32 device_id, const std::string& device_name); ReturnCode Open(const OpenRequest& request) override; - void Close() override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; }; diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 29ea0de0fb..1ff4064c1a 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -4,6 +4,7 @@ #include "Core/IOS/ES/ES.h" +#include #include #include #include @@ -27,17 +28,13 @@ namespace HLE { namespace Device { -// Shared across all ES instances. +// TODO: drop this and convert the title context into a member once the WAD launch hack is gone. static std::string s_content_file; static TitleContext s_title_context; // Title to launch after IOS has been reset and reloaded (similar to /sys/launch.sys). static u64 s_title_to_launch; -ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) -{ -} - static void FinishAllStaleImports() { const std::vector titles = IOS::ES::GetTitleImports(); @@ -58,7 +55,7 @@ static void FinishAllStaleImports() File::CreateDir(import_dir); } -void ES::Init() +ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) { FinishAllStaleImports(); @@ -182,14 +179,14 @@ static ReturnCode CheckIsAllowedToSetUID(const u32 caller_uid) return caller_uid == system_menu_uid ? IPC_SUCCESS : ES_EINVAL; } -IPCCommandResult ES::SetUID(const IOCtlVRequest& request) +IPCCommandResult ES::SetUID(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8) return GetDefaultReply(ES_EINVAL); const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); - const s32 ret = CheckIsAllowedToSetUID(m_caller_uid); + const s32 ret = CheckIsAllowedToSetUID(uid); if (ret < 0) { ERROR_LOG(IOS_ES, "SetUID: Permission check failed with error %d", ret); @@ -279,6 +276,24 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) return BootstrapPPC(content_loader); } +void ES::Context::DoState(PointerWrap& p) +{ + p.Do(uid); + p.Do(gid); + + title_import.tmd.DoState(p); + p.Do(title_import.content_id); + p.Do(title_import.content_buffer); + + p.Do(title_export.valid); + title_export.tmd.DoState(p); + p.Do(title_export.title_key); + p.Do(title_export.contents); + + p.Do(active); + p.Do(ipc_fd); +} + void ES::DoState(PointerWrap& p) { Device::DoState(p); @@ -286,17 +301,8 @@ void ES::DoState(PointerWrap& p) p.Do(m_AccessIdentID); s_title_context.DoState(p); - m_addtitle_tmd.DoState(p); - p.Do(m_addtitle_content_id); - p.Do(m_addtitle_content_buffer); - - p.Do(m_caller_uid); - p.Do(m_caller_gid); - - p.Do(m_export_title_context.valid); - m_export_title_context.tmd.DoState(p); - p.Do(m_export_title_context.title_key); - p.Do(m_export_title_context.contents); + for (auto& context : m_contexts) + context.DoState(p); u32 Count = (u32)(m_ContentAccessMap.size()); p.Do(Count); @@ -322,16 +328,41 @@ void ES::DoState(PointerWrap& p) } } +ES::ContextArray::iterator ES::FindActiveContext(u32 fd) +{ + return std::find_if(m_contexts.begin(), m_contexts.end(), + [fd](const auto& context) { return context.ipc_fd == fd && context.active; }); +} + +ES::ContextArray::iterator ES::FindInactiveContext() +{ + return std::find_if(m_contexts.begin(), m_contexts.end(), + [](const auto& context) { return !context.active; }); +} + ReturnCode ES::Open(const OpenRequest& request) { - m_caller_uid = request.uid; - m_caller_gid = request.gid; + auto context = FindInactiveContext(); + if (context == m_contexts.end()) + return ES_FD_EXHAUSTED; + + context->active = true; + context->uid = request.uid; + context->gid = request.gid; + context->ipc_fd = request.fd; return Device::Open(request); } -void ES::Close() +ReturnCode ES::Close(u32 fd) { - // XXX: does IOS really clear the content access map here? + auto context = FindActiveContext(fd); + if (context == m_contexts.end()) + return ES_EINVAL; + + context->active = false; + context->ipc_fd = -1; + + // FIXME: IOS doesn't clear the content access map here. m_ContentAccessMap.clear(); m_AccessIdentID = 0; @@ -339,48 +370,52 @@ void ES::Close() m_is_active = false; // clear the NAND content cache to make sure nothing remains open. DiscIO::CNANDContentManager::Access().ClearCache(); + return IPC_SUCCESS; } IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) { DEBUG_LOG(IOS_ES, "%s (0x%x)", GetDeviceName().c_str(), request.request); + auto context = FindActiveContext(request.fd); + if (context == m_contexts.end()) + return GetDefaultReply(ES_EINVAL); switch (request.request) { case IOCTL_ES_ADDTICKET: return AddTicket(request); case IOCTL_ES_ADDTMD: - return AddTMD(request); + return AddTMD(*context, request); case IOCTL_ES_ADDTITLESTART: - return AddTitleStart(request); + return AddTitleStart(*context, request); case IOCTL_ES_ADDCONTENTSTART: - return AddContentStart(request); + return AddContentStart(*context, request); case IOCTL_ES_ADDCONTENTDATA: - return AddContentData(request); + return AddContentData(*context, request); case IOCTL_ES_ADDCONTENTFINISH: - return AddContentFinish(request); + return AddContentFinish(*context, request); case IOCTL_ES_ADDTITLEFINISH: - return AddTitleFinish(request); + return AddTitleFinish(*context, request); case IOCTL_ES_ADDTITLECANCEL: - return AddTitleCancel(request); + return AddTitleCancel(*context, request); case IOCTL_ES_GETDEVICEID: return GetConsoleID(request); case IOCTL_ES_OPENTITLECONTENT: - return OpenTitleContent(request); + return OpenTitleContent(context->uid, request); case IOCTL_ES_OPENCONTENT: - return OpenContent(request); + return OpenContent(context->uid, request); case IOCTL_ES_READCONTENT: - return ReadContent(request); + return ReadContent(context->uid, request); case IOCTL_ES_CLOSECONTENT: - return CloseContent(request); + return CloseContent(context->uid, request); case IOCTL_ES_SEEKCONTENT: - return SeekContent(request); + return SeekContent(context->uid, request); case IOCTL_ES_GETTITLEDIR: return GetTitleDirectory(request); case IOCTL_ES_GETTITLEID: return GetTitleID(request); case IOCTL_ES_SETUID: - return SetUID(request); + return SetUID(context->uid, request); case IOCTL_ES_DIVERIFY: return DIVerify(request); @@ -441,23 +476,23 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) case IOCTL_ES_GETSTOREDTMD: return GetStoredTMD(request); case IOCTL_ES_ENCRYPT: - return Encrypt(request); + return Encrypt(context->uid, request); case IOCTL_ES_DECRYPT: - return Decrypt(request); + return Decrypt(context->uid, request); case IOCTL_ES_LAUNCH: return Launch(request); case IOCTL_ES_LAUNCHBC: return LaunchBC(request); case IOCTL_ES_EXPORTTITLEINIT: - return ExportTitleInit(request); + return ExportTitleInit(*context, request); case IOCTL_ES_EXPORTCONTENTBEGIN: - return ExportContentBegin(request); + return ExportContentBegin(*context, request); case IOCTL_ES_EXPORTCONTENTDATA: - return ExportContentData(request); + return ExportContentData(*context, request); case IOCTL_ES_EXPORTCONTENTEND: - return ExportContentEnd(request); + return ExportContentEnd(*context, request); case IOCTL_ES_EXPORTTITLEDONE: - return ExportTitleDone(request); + return ExportTitleDone(*context, request); case IOCTL_ES_CHECKKOREAREGION: return CheckKoreaRegion(request); case IOCTL_ES_GETDEVICECERT: diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index e7cb5c6c45..e060f51af4 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -45,9 +45,6 @@ class ES final : public Device public: ES(u32 device_id, const std::string& device_name); - // Called after an IOS reload. - static void Init(); - static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket); static void LoadWAD(const std::string& _rContentFile); static bool LaunchTitle(u64 title_id, bool skip_reload = false); @@ -58,7 +55,7 @@ public: void DoState(PointerWrap& p) override; ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; private: @@ -155,20 +152,57 @@ private: u8 padding[0x3c]; }; + struct TitleImportContext + { + IOS::ES::TMDReader tmd; + u32 content_id = 0xFFFFFFFF; + std::vector content_buffer; + }; + + // TODO: merge this with TitleImportContext. Also reuse the global content table. + struct TitleExportContext + { + struct ExportContent + { + OpenedContent content; + std::array iv{}; + }; + + bool valid = false; + IOS::ES::TMDReader tmd; + std::vector title_key; + std::map contents; + }; + + struct Context + { + void DoState(PointerWrap& p); + + u16 gid = 0; + u32 uid = 0; + TitleImportContext title_import; + TitleExportContext title_export; + bool active = false; + // We use this to associate an IPC fd with an ES context. + u32 ipc_fd = -1; + }; + // ES can only have 3 contexts at one time. + using ContextArray = std::array; + // Title management IPCCommandResult AddTicket(const IOCtlVRequest& request); - IPCCommandResult AddTMD(const IOCtlVRequest& request); - IPCCommandResult AddTitleStart(const IOCtlVRequest& request); - IPCCommandResult AddContentStart(const IOCtlVRequest& request); - IPCCommandResult AddContentData(const IOCtlVRequest& request); - IPCCommandResult AddContentFinish(const IOCtlVRequest& request); - IPCCommandResult AddTitleFinish(const IOCtlVRequest& request); - IPCCommandResult AddTitleCancel(const IOCtlVRequest& request); - IPCCommandResult ExportTitleInit(const IOCtlVRequest& request); - IPCCommandResult ExportContentBegin(const IOCtlVRequest& request); - IPCCommandResult ExportContentData(const IOCtlVRequest& request); - IPCCommandResult ExportContentEnd(const IOCtlVRequest& request); - IPCCommandResult ExportTitleDone(const IOCtlVRequest& request); + IPCCommandResult AddTMD(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddTitleStart(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddContentStart(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddContentData(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddContentFinish(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddTitleFinish(Context& context, const IOCtlVRequest& request); + IPCCommandResult AddTitleCancel(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportTitleInit(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportContentBegin(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportContentData(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportContentEnd(Context& context, const IOCtlVRequest& request); + IPCCommandResult ExportTitleDone(Context& context, const IOCtlVRequest& request); IPCCommandResult DeleteTitle(const IOCtlVRequest& request); IPCCommandResult DeleteTicket(const IOCtlVRequest& request); IPCCommandResult DeleteTitleContent(const IOCtlVRequest& request); @@ -178,11 +212,11 @@ private: IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request); IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request); IPCCommandResult Sign(const IOCtlVRequest& request); - IPCCommandResult Encrypt(const IOCtlVRequest& request); - IPCCommandResult Decrypt(const IOCtlVRequest& request); + IPCCommandResult Encrypt(u32 uid, const IOCtlVRequest& request); + IPCCommandResult Decrypt(u32 uid, const IOCtlVRequest& request); // Misc - IPCCommandResult SetUID(const IOCtlVRequest& request); + IPCCommandResult SetUID(u32 uid, const IOCtlVRequest& request); IPCCommandResult GetTitleDirectory(const IOCtlVRequest& request); IPCCommandResult GetTitleID(const IOCtlVRequest& request); IPCCommandResult GetConsumption(const IOCtlVRequest& request); @@ -191,11 +225,11 @@ private: IPCCommandResult DIVerify(const IOCtlVRequest& request); // Title contents - IPCCommandResult OpenTitleContent(const IOCtlVRequest& request); - IPCCommandResult OpenContent(const IOCtlVRequest& request); - IPCCommandResult ReadContent(const IOCtlVRequest& request); - IPCCommandResult CloseContent(const IOCtlVRequest& request); - IPCCommandResult SeekContent(const IOCtlVRequest& request); + IPCCommandResult OpenTitleContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult OpenContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult ReadContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult CloseContent(u32 uid, const IOCtlVRequest& request); + IPCCommandResult SeekContent(u32 uid, const IOCtlVRequest& request); // Title information IPCCommandResult GetTitleCount(const std::vector& titles, const IOCtlVRequest& request); @@ -228,6 +262,9 @@ private: IPCCommandResult DIGetTMDSize(const IOCtlVRequest& request); IPCCommandResult DIGetTMD(const IOCtlVRequest& request); + ContextArray::iterator FindActiveContext(u32 fd); + ContextArray::iterator FindInactiveContext(); + static bool LaunchIOS(u64 ios_title_id); static bool LaunchPPCTitle(u64 title_id, bool skip_reload); static TitleContext& GetTitleContext(); @@ -241,27 +278,7 @@ private: u32 m_AccessIdentID = 0; - // For title installation (ioctls IOCTL_ES_ADDTITLE*). - IOS::ES::TMDReader m_addtitle_tmd; - u32 m_addtitle_content_id = 0xFFFFFFFF; - std::vector m_addtitle_content_buffer; - - u32 m_caller_uid = 0; - u16 m_caller_gid = 0; - - struct TitleExportContext - { - struct ExportContent - { - OpenedContent content; - std::array iv{}; - }; - - bool valid = false; - IOS::ES::TMDReader tmd; - std::vector title_key; - std::map contents; - } m_export_title_context; + ContextArray m_contexts; }; } // namespace Device } // namespace HLE diff --git a/Source/Core/Core/IOS/ES/Identity.cpp b/Source/Core/Core/IOS/ES/Identity.cpp index c4b5722ee0..3ae6ba5083 100644 --- a/Source/Core/Core/IOS/ES/Identity.cpp +++ b/Source/Core/Core/IOS/ES/Identity.cpp @@ -63,7 +63,7 @@ IPCCommandResult ES::GetConsoleID(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::Encrypt(const IOCtlVRequest& request) +IPCCommandResult ES::Encrypt(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 2)) return GetDefaultReply(ES_EINVAL); @@ -85,7 +85,7 @@ IPCCommandResult ES::Encrypt(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::Decrypt(const IOCtlVRequest& request) +IPCCommandResult ES::Decrypt(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 2)) return GetDefaultReply(ES_EINVAL); diff --git a/Source/Core/Core/IOS/ES/TitleContents.cpp b/Source/Core/Core/IOS/ES/TitleContents.cpp index d97b74d7d9..6a5fc64965 100644 --- a/Source/Core/Core/IOS/ES/TitleContents.cpp +++ b/Source/Core/Core/IOS/ES/TitleContents.cpp @@ -48,7 +48,7 @@ u32 ES::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index) return CFD; } -IPCCommandResult ES::OpenTitleContent(const IOCtlVRequest& request) +IPCCommandResult ES::OpenTitleContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 0)) return GetDefaultReply(ES_EINVAL); @@ -64,7 +64,7 @@ IPCCommandResult ES::OpenTitleContent(const IOCtlVRequest& request) return GetDefaultReply(CFD); } -IPCCommandResult ES::OpenContent(const IOCtlVRequest& request) +IPCCommandResult ES::OpenContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); @@ -79,7 +79,7 @@ IPCCommandResult ES::OpenContent(const IOCtlVRequest& request) return GetDefaultReply(CFD); } -IPCCommandResult ES::ReadContent(const IOCtlVRequest& request) +IPCCommandResult ES::ReadContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1)) return GetDefaultReply(ES_EINVAL); @@ -131,7 +131,7 @@ IPCCommandResult ES::ReadContent(const IOCtlVRequest& request) return GetDefaultReply(Size); } -IPCCommandResult ES::CloseContent(const IOCtlVRequest& request) +IPCCommandResult ES::CloseContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); @@ -160,7 +160,7 @@ IPCCommandResult ES::CloseContent(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::SeekContent(const IOCtlVRequest& request) +IPCCommandResult ES::SeekContent(u32 uid, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(3, 0)) return GetDefaultReply(ES_EINVAL); diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index a01e0f758c..8426b15582 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -66,7 +66,7 @@ IPCCommandResult ES::AddTicket(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTMD(const IOCtlVRequest& request) +IPCCommandResult ES::AddTMD(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); @@ -76,18 +76,18 @@ IPCCommandResult ES::AddTMD(const IOCtlVRequest& request) // Ioctlv 0x2b writes the TMD to /tmp/title.tmd (for imports) and doesn't seem to write it // to either /import or /title. So here we simply have to set the import TMD. - m_addtitle_tmd.SetBytes(std::move(tmd)); + context.title_import.tmd.SetBytes(std::move(tmd)); // TODO: validate TMDs and return the proper error code (-1027) if the signature type is invalid. - if (!m_addtitle_tmd.IsValid()) + if (!context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - if (!IOS::ES::InitImport(m_addtitle_tmd.GetTitleId())) + if (!IOS::ES::InitImport(context.title_import.tmd.GetTitleId())) return GetDefaultReply(FS_EIO); return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request) +IPCCommandResult ES::AddTitleStart(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(4, 0)) return GetDefaultReply(ES_EINVAL); @@ -96,19 +96,20 @@ IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request) std::vector tmd(request.in_vectors[0].size); Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size); - m_addtitle_tmd.SetBytes(tmd); - if (!m_addtitle_tmd.IsValid()) + context.title_import.tmd.SetBytes(tmd); + if (!context.title_import.tmd.IsValid()) { ERROR_LOG(IOS_ES, "Invalid TMD while adding title (size = %zd)", tmd.size()); return GetDefaultReply(ES_EINVAL); } // Finish a previous import (if it exists). - const IOS::ES::TMDReader previous_tmd = IOS::ES::FindImportTMD(m_addtitle_tmd.GetTitleId()); + const IOS::ES::TMDReader previous_tmd = + IOS::ES::FindImportTMD(context.title_import.tmd.GetTitleId()); if (previous_tmd.IsValid()) FinishImport(previous_tmd); - if (!IOS::ES::InitImport(m_addtitle_tmd.GetTitleId())) + if (!IOS::ES::InitImport(context.title_import.tmd.GetTitleId())) return GetDefaultReply(FS_EIO); // TODO: check and use the other vectors. @@ -116,7 +117,7 @@ IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request) +IPCCommandResult ES::AddContentStart(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0)) return GetDefaultReply(ES_EINVAL); @@ -124,28 +125,28 @@ IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request) u64 title_id = Memory::Read_U64(request.in_vectors[0].address); u32 content_id = Memory::Read_U32(request.in_vectors[1].address); - if (m_addtitle_content_id != 0xFFFFFFFF) + if (context.title_import.content_id != 0xFFFFFFFF) { ERROR_LOG(IOS_ES, "Trying to add content when we haven't finished adding " "another content. Unsupported."); return GetDefaultReply(ES_EINVAL); } - m_addtitle_content_id = content_id; + context.title_import.content_id = content_id; - m_addtitle_content_buffer.clear(); + context.title_import.content_buffer.clear(); INFO_LOG(IOS_ES, "IOCTL_ES_ADDCONTENTSTART: title id %016" PRIx64 ", " "content id %08x", - title_id, m_addtitle_content_id); + title_id, context.title_import.content_id); - if (!m_addtitle_tmd.IsValid()) + if (!context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - if (title_id != m_addtitle_tmd.GetTitleId()) + if (title_id != context.title_import.tmd.GetTitleId()) { ERROR_LOG(IOS_ES, "IOCTL_ES_ADDCONTENTSTART: title id %016" PRIx64 " != " "TMD title id %016" PRIx64 ", ignoring", - title_id, m_addtitle_tmd.GetTitleId()); + title_id, context.title_import.tmd.GetTitleId()); } // We're supposed to return a "content file descriptor" here, which is @@ -156,7 +157,7 @@ IPCCommandResult ES::AddContentStart(const IOCtlVRequest& request) return GetDefaultReply(content_fd); } -IPCCommandResult ES::AddContentData(const IOCtlVRequest& request) +IPCCommandResult ES::AddContentData(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0)) return GetDefaultReply(ES_EINVAL); @@ -168,7 +169,8 @@ IPCCommandResult ES::AddContentData(const IOCtlVRequest& request) u8* data_start = Memory::GetPointer(request.in_vectors[1].address); u8* data_end = data_start + request.in_vectors[1].size; - m_addtitle_content_buffer.insert(m_addtitle_content_buffer.end(), data_start, data_end); + context.title_import.content_buffer.insert(context.title_import.content_buffer.end(), data_start, + data_end); return GetDefaultReply(IPC_SUCCESS); } @@ -184,22 +186,22 @@ static std::string GetImportContentPath(u64 title_id, u32 content_id) return Common::GetImportTitlePath(title_id) + StringFromFormat("/content/%08x.app", content_id); } -IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) +IPCCommandResult ES::AddContentFinish(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0)) return GetDefaultReply(ES_EINVAL); - if (m_addtitle_content_id == 0xFFFFFFFF) + if (context.title_import.content_id == 0xFFFFFFFF) return GetDefaultReply(ES_EINVAL); u32 content_fd = Memory::Read_U32(request.in_vectors[0].address); INFO_LOG(IOS_ES, "IOCTL_ES_ADDCONTENTFINISH: content fd %08x", content_fd); - if (!m_addtitle_tmd.IsValid()) + if (!context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); // Try to find the title key from a pre-installed ticket. - IOS::ES::TicketReader ticket = DiscIO::FindSignedTicket(m_addtitle_tmd.GetTitleId()); + IOS::ES::TicketReader ticket = DiscIO::FindSignedTicket(context.title_import.tmd.GetTitleId()); if (!ticket.IsValid()) { return GetDefaultReply(ES_NO_TICKET); @@ -211,16 +213,16 @@ IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) // The IV for title content decryption is the lower two bytes of the // content index, zero extended. IOS::ES::Content content_info; - if (!m_addtitle_tmd.FindContentById(m_addtitle_content_id, &content_info)) + if (!context.title_import.tmd.FindContentById(context.title_import.content_id, &content_info)) { return GetDefaultReply(ES_EINVAL); } u8 iv[16] = {0}; iv[0] = (content_info.index >> 8) & 0xFF; iv[1] = content_info.index & 0xFF; - std::vector decrypted_data(m_addtitle_content_buffer.size()); - mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, m_addtitle_content_buffer.size(), iv, - m_addtitle_content_buffer.data(), decrypted_data.data()); + std::vector decrypted_data(context.title_import.content_buffer.size()); + mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, context.title_import.content_buffer.size(), + iv, context.title_import.content_buffer.data(), decrypted_data.data()); if (!CheckIfContentHashMatches(decrypted_data, content_info)) { ERROR_LOG(IOS_ES, "AddContentFinish: Hash for content %08x doesn't match", content_info.id); @@ -235,12 +237,13 @@ IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) } else { - content_path = GetImportContentPath(m_addtitle_tmd.GetTitleId(), m_addtitle_content_id); + content_path = GetImportContentPath(context.title_import.tmd.GetTitleId(), + context.title_import.content_id); } File::CreateFullPath(content_path); const std::string temp_path = Common::RootUserPath(Common::FROM_SESSION_ROOT) + - StringFromFormat("/tmp/%08x.app", m_addtitle_content_id); + StringFromFormat("/tmp/%08x.app", context.title_import.content_id); File::CreateFullPath(temp_path); { @@ -258,32 +261,33 @@ IPCCommandResult ES::AddContentFinish(const IOCtlVRequest& request) return GetDefaultReply(ES_EIO); } - m_addtitle_content_id = 0xFFFFFFFF; + context.title_import.content_id = 0xFFFFFFFF; return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTitleFinish(const IOCtlVRequest& request) +IPCCommandResult ES::AddTitleFinish(Context& context, const IOCtlVRequest& request) { - if (!request.HasNumberOfValidVectors(0, 0) || !m_addtitle_tmd.IsValid()) + if (!request.HasNumberOfValidVectors(0, 0) || !context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - if (!WriteImportTMD(m_addtitle_tmd)) + if (!WriteImportTMD(context.title_import.tmd)) return GetDefaultReply(ES_EIO); - if (!FinishImport(m_addtitle_tmd)) + if (!FinishImport(context.title_import.tmd)) return GetDefaultReply(FS_EIO); INFO_LOG(IOS_ES, "IOCTL_ES_ADDTITLEFINISH"); - m_addtitle_tmd.SetBytes({}); + context.title_import.tmd.SetBytes({}); return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::AddTitleCancel(const IOCtlVRequest& request) +IPCCommandResult ES::AddTitleCancel(Context& context, const IOCtlVRequest& request) { - if (!request.HasNumberOfValidVectors(0, 0) || !m_addtitle_tmd.IsValid()) + if (!request.HasNumberOfValidVectors(0, 0) || !context.title_import.tmd.IsValid()) return GetDefaultReply(ES_EINVAL); - const IOS::ES::TMDReader original_tmd = IOS::ES::FindInstalledTMD(m_addtitle_tmd.GetTitleId()); + const IOS::ES::TMDReader original_tmd = + IOS::ES::FindInstalledTMD(context.title_import.tmd.GetTitleId()); if (!original_tmd.IsValid()) { // This should never happen unless someone messed with the installed TMD directly. @@ -294,7 +298,7 @@ IPCCommandResult ES::AddTitleCancel(const IOCtlVRequest& request) if (!FinishImport(original_tmd)) return GetDefaultReply(FS_EIO); - m_addtitle_tmd.SetBytes({}); + context.title_import.tmd.SetBytes({}); return GetDefaultReply(IPC_SUCCESS); } @@ -363,40 +367,40 @@ IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportTitleInit(const IOCtlVRequest& request) +IPCCommandResult ES::ExportTitleInit(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8) return GetDefaultReply(ES_EINVAL); // No concurrent title import/export is allowed. - if (m_export_title_context.valid) + if (context.title_export.valid) return GetDefaultReply(ES_EINVAL); const auto tmd = IOS::ES::FindInstalledTMD(Memory::Read_U64(request.in_vectors[0].address)); if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - m_export_title_context.tmd = tmd; + context.title_export.tmd = tmd; - const auto ticket = DiscIO::FindSignedTicket(m_export_title_context.tmd.GetTitleId()); + const auto ticket = DiscIO::FindSignedTicket(context.title_export.tmd.GetTitleId()); if (!ticket.IsValid()) return GetDefaultReply(ES_NO_TICKET); - if (ticket.GetTitleId() != m_export_title_context.tmd.GetTitleId()) + if (ticket.GetTitleId() != context.title_export.tmd.GetTitleId()) return GetDefaultReply(ES_EINVAL); - m_export_title_context.title_key = ticket.GetTitleKey(); + context.title_export.title_key = ticket.GetTitleKey(); - const auto& raw_tmd = m_export_title_context.tmd.GetRawTMD(); + const auto& raw_tmd = context.title_export.tmd.GetRawTMD(); if (request.io_vectors[0].size != raw_tmd.size()) return GetDefaultReply(ES_EINVAL); Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size()); - m_export_title_context.valid = true; + context.title_export.valid = true; return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) +IPCCommandResult ES::ExportContentBegin(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != 8 || request.in_vectors[1].size != 4) @@ -405,7 +409,7 @@ IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); const u32 content_id = Memory::Read_U32(request.in_vectors[1].address); - if (!m_export_title_context.valid || m_export_title_context.tmd.GetTitleId() != title_id) + if (!context.title_export.valid || context.title_export.tmd.GetTitleId() != title_id) { ERROR_LOG(IOS_ES, "Tried to use ExportContentBegin with an invalid title export context."); return GetDefaultReply(ES_EINVAL); @@ -426,7 +430,7 @@ IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) content->m_Data->Open(); u32 cid = 0; - while (m_export_title_context.contents.find(cid) != m_export_title_context.contents.end()) + while (context.title_export.contents.find(cid) != context.title_export.contents.end()) cid++; TitleExportContext::ExportContent content_export; @@ -434,12 +438,12 @@ IPCCommandResult ES::ExportContentBegin(const IOCtlVRequest& request) content_export.iv[0] = (content->m_metadata.index >> 8) & 0xFF; content_export.iv[1] = content->m_metadata.index & 0xFF; - m_export_title_context.contents.emplace(cid, content_export); + context.title_export.contents.emplace(cid, content_export); // IOS returns a content ID which is passed to further content calls. return GetDefaultReply(cid); } -IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) +IPCCommandResult ES::ExportContentData(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 4 || request.io_vectors[0].size == 0) @@ -450,8 +454,8 @@ IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) const u32 content_id = Memory::Read_U32(request.in_vectors[0].address); const u32 bytes_to_read = request.io_vectors[0].size; - const auto iterator = m_export_title_context.contents.find(content_id); - if (!m_export_title_context.valid || iterator == m_export_title_context.contents.end() || + const auto iterator = context.title_export.contents.find(content_id); + if (!context.title_export.valid || iterator == context.title_export.contents.end() || iterator->second.content.m_position >= iterator->second.content.m_content.size) { return GetDefaultReply(ES_EINVAL); @@ -479,7 +483,7 @@ IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) std::vector output(buffer.size()); mbedtls_aes_context aes_ctx; - mbedtls_aes_setkey_enc(&aes_ctx, m_export_title_context.title_key.data(), 128); + mbedtls_aes_setkey_enc(&aes_ctx, context.title_export.title_key.data(), 128); const int ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer.size(), iterator->second.iv.data(), buffer.data(), output.data()); if (ret != 0) @@ -494,15 +498,15 @@ IPCCommandResult ES::ExportContentData(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportContentEnd(const IOCtlVRequest& request) +IPCCommandResult ES::ExportContentEnd(Context& context, const IOCtlVRequest& request) { if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4) return GetDefaultReply(ES_EINVAL); const u32 content_id = Memory::Read_U32(request.in_vectors[0].address); - const auto iterator = m_export_title_context.contents.find(content_id); - if (!m_export_title_context.valid || iterator == m_export_title_context.contents.end() || + const auto iterator = context.title_export.contents.find(content_id); + if (!context.title_export.valid || iterator == context.title_export.contents.end() || iterator->second.content.m_position != iterator->second.content.m_content.size) { return GetDefaultReply(ES_EINVAL); @@ -513,16 +517,16 @@ IPCCommandResult ES::ExportContentEnd(const IOCtlVRequest& request) const auto& content_loader = AccessContentDevice(iterator->second.content.m_title_id); content_loader.GetContentByID(iterator->second.content.m_content.id)->m_Data->Close(); - m_export_title_context.contents.erase(iterator); + context.title_export.contents.erase(iterator); return GetDefaultReply(IPC_SUCCESS); } -IPCCommandResult ES::ExportTitleDone(const IOCtlVRequest& request) +IPCCommandResult ES::ExportTitleDone(Context& context, const IOCtlVRequest& request) { - if (!m_export_title_context.valid) + if (!context.title_export.valid) return GetDefaultReply(ES_EINVAL); - m_export_title_context.valid = false; + context.title_export.valid = false; return GetDefaultReply(IPC_SUCCESS); } } // namespace Device diff --git a/Source/Core/Core/IOS/FS/FileIO.cpp b/Source/Core/Core/IOS/FS/FileIO.cpp index dbc2f02014..4c11d8267c 100644 --- a/Source/Core/Core/IOS/FS/FileIO.cpp +++ b/Source/Core/Core/IOS/FS/FileIO.cpp @@ -76,7 +76,7 @@ FileIO::FileIO(u32 device_id, const std::string& device_name) { } -void FileIO::Close() +ReturnCode FileIO::Close(u32 fd) { INFO_LOG(IOS_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id); m_Mode = 0; @@ -86,6 +86,7 @@ void FileIO::Close() m_file.reset(); m_is_active = false; + return IPC_SUCCESS; } ReturnCode FileIO::Open(const OpenRequest& request) diff --git a/Source/Core/Core/IOS/FS/FileIO.h b/Source/Core/Core/IOS/FS/FileIO.h index 0e5698c5b5..f341208d9c 100644 --- a/Source/Core/Core/IOS/FS/FileIO.h +++ b/Source/Core/Core/IOS/FS/FileIO.h @@ -32,7 +32,7 @@ class FileIO : public Device public: FileIO(u32 device_id, const std::string& device_name); - void Close() override; + ReturnCode Close(u32 fd) override; ReturnCode Open(const OpenRequest& request) override; IPCCommandResult Seek(const SeekRequest& request) override; IPCCommandResult Read(const ReadWriteRequest& request) override; diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp index 00d20877f9..2906f207c2 100644 --- a/Source/Core/Core/IOS/IPC.cpp +++ b/Source/Core/Core/IOS/IPC.cpp @@ -75,9 +75,7 @@ static std::mutex s_device_map_mutex; // STATE_TO_SAVE constexpr u8 IPC_MAX_FDS = 0x18; -constexpr u8 ES_MAX_COUNT = 3; static std::shared_ptr s_fdmap[IPC_MAX_FDS]; -static std::shared_ptr s_es_handles[ES_MAX_COUNT]; using IPCMsgQueue = std::deque; static IPCMsgQueue s_request_queue; // ppc -> arm @@ -595,11 +593,7 @@ static void AddStaticDevices() AddDevice("/dev/stm/immediate"); AddDevice("/dev/stm/eventhook"); AddDevice("/dev/fs"); - - // IOS allows three ES devices at a time - for (auto& es_device : s_es_handles) - es_device = AddDevice("/dev/es"); - + AddDevice("/dev/es"); AddDevice("/dev/di"); AddDevice("/dev/net/kd/request"); AddDevice("/dev/net/kd/time"); @@ -643,7 +637,7 @@ static void Reset() { if (!device) continue; - device->Close(); + device->Close(0); device.reset(); } @@ -701,7 +695,6 @@ bool Reload(const u64 ios_title_id) AddStaticDevices(); - Device::ES::Init(); return true; } @@ -855,13 +848,6 @@ void DoState(PointerWrap& p) } } } - - for (auto& es_device : s_es_handles) - { - const u32 handle_id = es_device->GetDeviceID(); - p.Do(handle_id); - es_device = std::static_pointer_cast(AccessDeviceByID(handle_id)); - } } else { @@ -884,24 +870,11 @@ void DoState(PointerWrap& p) } } } - - for (const auto& es_device : s_es_handles) - { - const u32 handle_id = es_device->GetDeviceID(); - p.Do(handle_id); - } } } -static std::shared_ptr GetUnusedESDevice() -{ - const auto iterator = std::find_if(std::begin(s_es_handles), std::end(s_es_handles), - [](const auto& es_device) { return !es_device->IsOpened(); }); - return (iterator != std::end(s_es_handles)) ? *iterator : nullptr; -} - // Returns the FD for the newly opened device (on success) or an error code. -static s32 OpenDevice(const OpenRequest& request) +static s32 OpenDevice(OpenRequest& request) { const s32 new_fd = GetFreeDeviceID(); INFO_LOG(IOS, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd); @@ -910,15 +883,10 @@ static s32 OpenDevice(const OpenRequest& request) ERROR_LOG(IOS, "Couldn't get a free fd, too many open files"); return FS_EFDEXHAUSTED; } + request.fd = new_fd; std::shared_ptr device; - if (request.path == "/dev/es") - { - device = GetUnusedESDevice(); - if (!device) - return ES_FD_EXHAUSTED; - } - else if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path)) + if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path)) { device = std::make_shared(new_fd, request.path); } @@ -961,8 +929,7 @@ static IPCCommandResult HandleCommand(const Request& request) { case IPC_CMD_CLOSE: s_fdmap[request.fd].reset(); - device->Close(); - return Device::Device::GetDefaultReply(IPC_SUCCESS); + return Device::Device::GetDefaultReply(device->Close(request.fd)); case IPC_CMD_READ: return device->Read(ReadWriteRequest{request.address}); case IPC_CMD_WRITE: diff --git a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp index 96a2d48219..4987fae39b 100644 --- a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp +++ b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp @@ -83,13 +83,13 @@ ReturnCode SDIOSlot0::Open(const OpenRequest& request) return IPC_SUCCESS; } -void SDIOSlot0::Close() +ReturnCode SDIOSlot0::Close(u32 fd) { m_Card.Close(); m_BlockLength = 0; m_BusWidth = 0; - m_is_active = false; + return Device::Close(fd); } IPCCommandResult SDIOSlot0::IOCtl(const IOCtlRequest& request) diff --git a/Source/Core/Core/IOS/SDIO/SDIOSlot0.h b/Source/Core/Core/IOS/SDIO/SDIOSlot0.h index 6fd08a9b16..116625f29b 100644 --- a/Source/Core/Core/IOS/SDIO/SDIOSlot0.h +++ b/Source/Core/Core/IOS/SDIO/SDIOSlot0.h @@ -31,7 +31,7 @@ public: void DoState(PointerWrap& p) override; ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; diff --git a/Source/Core/Core/IOS/STM/STM.cpp b/Source/Core/Core/IOS/STM/STM.cpp index 1330c42c65..aece7e39fa 100644 --- a/Source/Core/Core/IOS/STM/STM.cpp +++ b/Source/Core/Core/IOS/STM/STM.cpp @@ -67,10 +67,10 @@ IPCCommandResult STMImmediate::IOCtl(const IOCtlRequest& request) return GetDefaultReply(return_value); } -void STMEventHook::Close() +ReturnCode STMEventHook::Close(u32 fd) { s_event_hook_request.reset(); - m_is_active = false; + return Device::Close(fd); } IPCCommandResult STMEventHook::IOCtl(const IOCtlRequest& request) diff --git a/Source/Core/Core/IOS/STM/STM.h b/Source/Core/Core/IOS/STM/STM.h index 1a2f534d00..6721e3c28c 100644 --- a/Source/Core/Core/IOS/STM/STM.h +++ b/Source/Core/Core/IOS/STM/STM.h @@ -55,7 +55,7 @@ class STMEventHook final : public Device { public: STMEventHook(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {} - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp index 901aa11ef8..bf6c1c15d6 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp @@ -147,7 +147,7 @@ bool BluetoothEmu::RemoteDisconnect(u16 _connectionHandle) return SendEventDisconnect(_connectionHandle, 0x13); } -void BluetoothEmu::Close() +ReturnCode BluetoothEmu::Close(u32 fd) { // Clean up state m_ScanEnable = 0; @@ -156,7 +156,7 @@ void BluetoothEmu::Close() m_HCIEndpoint.reset(); m_ACLEndpoint.reset(); - m_is_active = false; + return Device::Close(fd); } IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request) diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h index 45e42ef45a..efb60cf10d 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h @@ -49,7 +49,7 @@ public: virtual ~BluetoothEmu(); - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; void Update() override; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp index cba2a3f394..25633158c1 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp @@ -149,7 +149,7 @@ ReturnCode BluetoothReal::Open(const OpenRequest& request) return IPC_SUCCESS; } -void BluetoothReal::Close() +ReturnCode BluetoothReal::Close(u32 fd) { if (m_handle) { @@ -159,7 +159,7 @@ void BluetoothReal::Close() m_handle = nullptr; } - m_is_active = false; + return Device::Close(fd); } IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request) diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h index dc1679925a..3acc462fc0 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h @@ -52,7 +52,7 @@ public: ~BluetoothReal() override; ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp index 61bbd447db..03b3e7da2c 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp @@ -68,9 +68,10 @@ ReturnCode OH0Device::Open(const OpenRequest& request) return return_code; } -void OH0Device::Close() +ReturnCode OH0Device::Close(u32 fd) { m_oh0->DeviceClose(m_device_id); + return Device::Close(fd); } IPCCommandResult OH0Device::IOCtl(const IOCtlRequest& request) diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.h b/Source/Core/Core/IOS/USB/OH0/OH0Device.h index 239622d227..c66ccc4b2f 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.h +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.h @@ -25,7 +25,7 @@ public: OH0Device(u32 device_id, const std::string& device_name); ReturnCode Open(const OpenRequest& request) override; - void Close() override; + ReturnCode Close(u32 fd) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 41a52669fc..fc2418391e 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 81; // Last changed in PR 5317 +static const u32 STATE_VERSION = 82; // Last changed in PR 5333 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list,