IOS: Clean up the way IPC replies are constructed

Instead of constructing IPCCommandResult with static member functions
in the Device class, we can just add the relevant constructors to the
reply struct itself. Makes more sense than putting it in Device
when the struct is used in the kernel code and doesn't use any Device
specific members...

This commit also changes the IPC command handlers to return an optional
IPCCommandResult rather than an IPCCommandResult. This removes the need
for a separate boolean that indicates whether the "result" is actually
a reply, and also avoids the need to set dummy result values and ticks.

It also makes it really obvious which commands can result in no reply
being generated.

Finally, this commit renames IPCCommandResult to IPCReply since the
struct is now only used for actual replies. This new name is less
verbose in my opinion.

The diff is quite large since this touches every command handler, but
the only functional change is that I fixed EnqueueIPCReply to
take a s64 for cycles_in_future to match IPCReply.
This commit is contained in:
Léo Lam 2021-02-13 18:33:23 +01:00
parent f52aa3d041
commit d0136dd7c2
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
61 changed files with 872 additions and 873 deletions

View File

@ -57,13 +57,13 @@ void DIDevice::DoState(PointerWrap& p)
p.Do(m_last_length);
}
IPCCommandResult DIDevice::Open(const OpenRequest& request)
std::optional<IPCReply> DIDevice::Open(const OpenRequest& request)
{
InitializeIfFirstTime();
return Device::Open(request);
}
IPCCommandResult DIDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> DIDevice::IOCtl(const IOCtlRequest& request)
{
InitializeIfFirstTime();
@ -91,7 +91,7 @@ IPCCommandResult DIDevice::IOCtl(const IOCtlRequest& request)
// FinishIOCtl will be called after the command has been executed
// to reply to the request, so we shouldn't reply here.
return GetNoReply();
return std::nullopt;
}
void DIDevice::ProcessQueuedIOCtl()
@ -612,7 +612,7 @@ void DIDevice::FinishDICommand(DIResult result)
}
}
IPCCommandResult DIDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
{
// IOCtlVs are not queued since they don't (currently) go into DVDInterface and act
// asynchronously. This does mean that an IOCtlV can be executed while an IOCtl is in progress,
@ -623,7 +623,7 @@ IPCCommandResult DIDevice::IOCtlV(const IOCtlVRequest& request)
{
ERROR_LOG_FMT(IOS_DI, "IOCtlV: Received bad input buffer size {:#04x}, should be 0x20",
request.in_vectors[0].size);
return GetDefaultReply(static_cast<s32>(DIResult::BadArgument));
return IPCReply{static_cast<s32>(DIResult::BadArgument)};
}
const u8 command = Memory::Read_U8(request.in_vectors[0].address);
if (request.request != command)
@ -704,7 +704,7 @@ IPCCommandResult DIDevice::IOCtlV(const IOCtlVRequest& request)
ERROR_LOG_FMT(IOS_DI, "Unknown ioctlv {:#04x}", request.request);
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_DI);
}
return GetDefaultReply(static_cast<s32>(return_value));
return IPCReply{static_cast<s32>(return_value)};
}
void DIDevice::ChangePartition(const DiscIO::Partition partition)

View File

@ -42,9 +42,9 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
enum class DIIoctl : u32
{

View File

@ -160,19 +160,19 @@ void Device::DoStateShared(PointerWrap& p)
p.Do(m_is_active);
}
IPCCommandResult Device::Open(const OpenRequest& request)
std::optional<IPCReply> Device::Open(const OpenRequest& request)
{
m_is_active = true;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply{IPC_SUCCESS};
}
IPCCommandResult Device::Close(u32 fd)
std::optional<IPCReply> Device::Close(u32 fd)
{
m_is_active = false;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply{IPC_SUCCESS};
}
IPCCommandResult Device::Unsupported(const Request& request)
std::optional<IPCReply> Device::Unsupported(const Request& request)
{
static const std::map<IPCCommandType, std::string_view> names{{
{IPC_CMD_READ, "Read"},
@ -183,27 +183,6 @@ IPCCommandResult Device::Unsupported(const Request& request)
}};
WARN_LOG_FMT(IOS, "{} does not support {}()", m_name, names.at(request.command));
return GetDefaultReply(IPC_EINVAL);
}
// Returns an IPCCommandResult for a reply with an average reply time for devices
// Please avoid using this function if more accurate timings are known.
IPCCommandResult Device::GetDefaultReply(const s32 return_value)
{
// Based on a hardware test, a device takes at least ~2700 ticks to reply to an IPC request.
// Depending on how much work a command performs, this can take much longer (10000+)
// especially if the NAND filesystem is accessed.
//
// Because we currently don't emulate timing very accurately, we should not return
// the minimum possible reply time (~960 ticks from the kernel or ~2700 from devices)
// but an average time, otherwise we are going to be much too fast in most cases.
return {return_value, true, 4000 * SystemTimers::TIMER_RATIO};
}
// Returns an IPCCommandResult with no reply. Useful for async commands that will generate a reply
// later. This takes no return value because it won't be used.
IPCCommandResult Device::GetNoReply()
{
return {IPC_SUCCESS, false, 0};
return IPCReply{IPC_EINVAL};
}
} // namespace IOS::HLE

View File

@ -5,6 +5,7 @@
#pragma once
#include <cstddef>
#include <optional>
#include <string>
#include <vector>
@ -186,19 +187,23 @@ public:
const std::string& GetDeviceName() const { return m_name; }
// Replies to Open and Close requests are sent by the IPC request handler (HandleCommand),
// not by the devices themselves.
virtual IPCCommandResult Open(const OpenRequest& request);
virtual IPCCommandResult 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); }
virtual IPCCommandResult IOCtl(const IOCtlRequest& ioctl) { return Unsupported(ioctl); }
virtual IPCCommandResult IOCtlV(const IOCtlVRequest& ioctlv) { return Unsupported(ioctlv); }
virtual std::optional<IPCReply> Open(const OpenRequest& request);
virtual std::optional<IPCReply> Close(u32 fd);
virtual std::optional<IPCReply> Seek(const SeekRequest& seek) { return Unsupported(seek); }
virtual std::optional<IPCReply> Read(const ReadWriteRequest& read) { return Unsupported(read); }
virtual std::optional<IPCReply> Write(const ReadWriteRequest& write)
{
return Unsupported(write);
}
virtual std::optional<IPCReply> IOCtl(const IOCtlRequest& ioctl) { return Unsupported(ioctl); }
virtual std::optional<IPCReply> IOCtlV(const IOCtlVRequest& ioctlv)
{
return Unsupported(ioctlv);
}
virtual void Update() {}
virtual void UpdateWantDeterminism(bool new_want_determinism) {}
virtual DeviceType GetDeviceType() const { return m_device_type; }
virtual bool IsOpened() const { return m_is_active; }
static IPCCommandResult GetDefaultReply(s32 return_value);
static IPCCommandResult GetNoReply();
protected:
Kernel& m_ios;
@ -209,6 +214,6 @@ protected:
bool m_is_active = false;
private:
IPCCommandResult Unsupported(const Request& request);
std::optional<IPCReply> Unsupported(const Request& request);
};
} // namespace IOS::HLE

View File

@ -8,22 +8,22 @@
namespace IOS::HLE
{
IPCCommandResult DeviceStub::Open(const OpenRequest& request)
std::optional<IPCReply> DeviceStub::Open(const OpenRequest& request)
{
WARN_LOG_FMT(IOS, "{} faking Open()", m_name);
m_is_active = true;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult DeviceStub::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> DeviceStub::IOCtl(const IOCtlRequest& request)
{
WARN_LOG_FMT(IOS, "{} faking IOCtl()", m_name);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult DeviceStub::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> DeviceStub::IOCtlV(const IOCtlVRequest& request)
{
WARN_LOG_FMT(IOS, "{} faking IOCtlV()", m_name);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE

View File

@ -17,8 +17,8 @@ class DeviceStub final : public Device
public:
// Inherit the constructor from the Device class, since we don't need to do anything special.
using Device::Device;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
};
} // namespace IOS::HLE

View File

@ -34,29 +34,29 @@ enum
};
IPCCommandResult GetSystemTime(const IOCtlVRequest& request)
IPCReply GetSystemTime(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.io_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const u32 milliseconds = Common::Timer::GetTimeMs();
Memory::Write_U32(milliseconds, request.io_vectors[0].address);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetVersion(const IOCtlVRequest& request)
IPCReply GetVersion(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const auto length = std::min(size_t(request.io_vectors[0].size), std::strlen(SCM_DESC_STR));
@ -64,19 +64,19 @@ IPCCommandResult GetVersion(const IOCtlVRequest& request)
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
Memory::CopyToEmu(request.io_vectors[0].address, SCM_DESC_STR, length);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetCPUSpeed(const IOCtlVRequest& request)
IPCReply GetCPUSpeed(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.io_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const SConfig& config = SConfig::GetInstance();
@ -86,66 +86,66 @@ IPCCommandResult GetCPUSpeed(const IOCtlVRequest& request)
Memory::Write_U32(core_clock, request.io_vectors[0].address);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetSpeedLimit(const IOCtlVRequest& request)
IPCReply GetSpeedLimit(const IOCtlVRequest& request)
{
// get current speed limit
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.io_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const SConfig& config = SConfig::GetInstance();
const u32 speed_percent = config.m_EmulationSpeed * 100;
Memory::Write_U32(speed_percent, request.io_vectors[0].address);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SetSpeedLimit(const IOCtlVRequest& request)
IPCReply SetSpeedLimit(const IOCtlVRequest& request)
{
// set current speed limit
if (!request.HasNumberOfValidVectors(1, 0))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
if (request.in_vectors[0].size != 4)
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const float speed = float(Memory::Read_U32(request.in_vectors[0].address)) / 100.0f;
SConfig::GetInstance().m_EmulationSpeed = speed;
BootManager::SetEmulationSpeedReset(true);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult GetRealProductCode(const IOCtlVRequest& request)
IPCReply GetRealProductCode(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
{
return DolphinDevice::GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
const std::string backup_file_path = File::GetUserPath(D_BACKUP_IDX) + DIR_SEP + WII_SETTING;
File::IOFile file(backup_file_path, "rb");
if (!file)
return DolphinDevice::GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
Common::SettingsHandler::Buffer data;
if (!file.ReadBytes(data.data(), data.size()))
return DolphinDevice::GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
Common::SettingsHandler gen;
gen.SetBytes(std::move(data));
@ -153,21 +153,19 @@ IPCCommandResult GetRealProductCode(const IOCtlVRequest& request)
const size_t length = std::min<size_t>(request.io_vectors[0].size, code.length());
if (length == 0)
return DolphinDevice::GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
Memory::CopyToEmu(request.io_vectors[0].address, code.c_str(), length);
return DolphinDevice::GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace
IPCCommandResult DolphinDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> DolphinDevice::IOCtlV(const IOCtlVRequest& request)
{
if (Core::WantsDeterminism())
{
return DolphinDevice::GetDefaultReply(IPC_EACCES);
}
return IPCReply(IPC_EACCES);
switch (request.request)
{
@ -184,7 +182,7 @@ IPCCommandResult DolphinDevice::IOCtlV(const IOCtlVRequest& request)
case IOCTL_DOLPHIN_GET_REAL_PRODUCTCODE:
return GetRealProductCode(request);
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
} // namespace IOS::HLE

View File

@ -13,6 +13,6 @@ class DolphinDevice final : public Device
public:
// Inherit the constructor from the Device class, since we don't need to do anything special.
using Device::Device;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
};
} // namespace IOS::HLE

View File

@ -120,10 +120,10 @@ void TitleContext::Update(const ES::TMDReader& tmd_, const ES::TicketReader& tic
}
}
IPCCommandResult ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
@ -132,7 +132,7 @@ IPCCommandResult ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
static_cast<u32>(title_id));
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETTITLEDIR: {}", path);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
ReturnCode ESDevice::GetTitleId(u64* title_id) const
@ -143,20 +143,20 @@ ReturnCode ESDevice::GetTitleId(u64* title_id) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::GetTitleId(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u64 title_id;
const ReturnCode ret = GetTitleId(&title_id);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
Memory::Write_U64(title_id, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETTITLEID: {:08x}/{:08x}", static_cast<u32>(title_id >> 32),
static_cast<u32>(title_id));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
static bool UpdateUIDAndGID(Kernel& kernel, const ES::TMDReader& tmd)
@ -196,10 +196,10 @@ static ReturnCode CheckIsAllowedToSetUID(Kernel& kernel, const u32 caller_uid,
return ES_EINVAL;
}
IPCCommandResult ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
@ -207,20 +207,20 @@ IPCCommandResult ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
if (ret < 0)
{
ERROR_LOG_FMT(IOS_ES, "SetUID: Permission check failed with error {}", ret);
return GetDefaultReply(ret);
return IPCReply(ret);
}
const auto tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
if (!UpdateUIDAndGID(m_ios, tmd))
{
ERROR_LOG_FMT(IOS_ES, "SetUID: Failed to get UID for title {:016x}", title_id);
return GetDefaultReply(ES_SHORT_READ);
return IPCReply(ES_SHORT_READ);
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
bool ESDevice::LaunchTitle(u64 title_id, bool skip_reload)
@ -380,11 +380,11 @@ ESDevice::ContextArray::iterator ESDevice::FindInactiveContext()
[](const auto& context) { return !context.active; });
}
IPCCommandResult ESDevice::Open(const OpenRequest& request)
std::optional<IPCReply> ESDevice::Open(const OpenRequest& request)
{
auto context = FindInactiveContext();
if (context == m_contexts.end())
return GetDefaultReply(ES_FD_EXHAUSTED);
return IPCReply{ES_FD_EXHAUSTED};
context->active = true;
context->uid = request.uid;
@ -393,26 +393,26 @@ IPCCommandResult ESDevice::Open(const OpenRequest& request)
return Device::Open(request);
}
IPCCommandResult ESDevice::Close(u32 fd)
std::optional<IPCReply> ESDevice::Close(u32 fd)
{
auto context = FindActiveContext(fd);
if (context == m_contexts.end())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
context->active = false;
context->ipc_fd = -1;
INFO_LOG_FMT(IOS_ES, "ES: Close");
m_is_active = false;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> ESDevice::IOCtlV(const IOCtlVRequest& request)
{
DEBUG_LOG_FMT(IOS_ES, "{} ({:#x})", GetDeviceName(), request.request);
auto context = FindActiveContext(request.fd);
if (context == m_contexts.end())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
switch (request.request)
{
@ -562,29 +562,29 @@ IPCCommandResult ESDevice::IOCtlV(const IOCtlVRequest& request)
PanicAlertFmt("IOS-ES: Unimplemented ioctlv {:#x} ({} in vectors, {} io vectors)",
request.request, request.in_vectors.size(), request.io_vectors.size());
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_ES, Common::Log::LERROR);
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
case IOCTL_ES_INVALID_3F:
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
IPCCommandResult ESDevice::GetConsumption(const IOCtlVRequest& request)
IPCReply ESDevice::GetConsumption(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// This is at least what crediar's ES module does
Memory::Write_U32(0, request.io_vectors[1].address);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETCONSUMPTION");
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::Launch(const IOCtlVRequest& request)
std::optional<IPCReply> ESDevice::Launch(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u32 view = Memory::Read_U32(request.in_vectors[1].address);
@ -598,41 +598,41 @@ IPCCommandResult ESDevice::Launch(const IOCtlVRequest& request)
// Prevent loading installed IOSes that are not emulated.
if (!IsEmulated(title_id))
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
// IOS replies to the request through the mailbox on failure, and acks if the launch succeeds.
// Note: Launch will potentially reset the whole IOS state -- including this ES instance.
if (!LaunchTitle(title_id))
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
// ES_LAUNCH involves restarting IOS, which results in two acknowledgements in a row
// (one from the previous IOS for this IPC request, and one from the new one as it boots).
// Nothing should be written to the command buffer if the launch succeeded for obvious reasons.
return GetNoReply();
return std::nullopt;
}
IPCCommandResult ESDevice::LaunchBC(const IOCtlVRequest& request)
std::optional<IPCReply> ESDevice::LaunchBC(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
// An alternative way to do this is to check whether the current active IOS is MIOS.
if (m_ios.GetVersion() == 0x101)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!LaunchTitle(0x0000000100000100))
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetNoReply();
return std::nullopt;
}
// This is technically an ioctlv in IOS's ES, but it is an internal API which cannot be
// used from the PowerPC (for unpatched and up-to-date IOSes anyway).
// So we block access to it from the IPC interface.
IPCCommandResult ESDevice::DIVerify(const IOCtlVRequest& request)
IPCReply ESDevice::DIVerify(const IOCtlVRequest& request)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
static ReturnCode WriteTmdForDiVerify(FS::FileSystem* fs, const ES::TMDReader& tmd)
@ -796,13 +796,13 @@ ReturnCode ESDevice::SetUpStreamKey(const u32 uid, const u8* ticket_view, const
&ticket_bytes[offsetof(ES::Ticket, title_key)], PID_ES);
}
IPCCommandResult ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
!ES::IsValidTMDSize(request.in_vectors[1].size) || request.io_vectors[0].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
std::vector<u8> tmd_bytes(request.in_vectors[1].size);
@ -810,22 +810,22 @@ IPCCommandResult ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRe
const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 handle;
const ReturnCode ret =
SetUpStreamKey(context.uid, Memory::GetPointer(request.in_vectors[0].address), tmd, &handle);
Memory::Write_U32(handle, request.io_vectors[0].address);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::DeleteStreamKey(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteStreamKey(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 handle = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(m_ios.GetIOSC().DeleteObject(handle, PID_ES));
return IPCReply(m_ios.GetIOSC().DeleteObject(handle, PID_ES));
}
bool ESDevice::IsActiveTitlePermittedByTicket(const u8* ticket_view) const

View File

@ -48,9 +48,9 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
struct TitleImportExportContext
{
@ -261,84 +261,84 @@ private:
using ContextArray = std::array<Context, 3>;
// Title management
IPCCommandResult ImportTicket(const IOCtlVRequest& request);
IPCCommandResult ImportTmd(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportTitleInit(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportContentBegin(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportContentData(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportContentEnd(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportTitleDone(Context& context, const IOCtlVRequest& request);
IPCCommandResult ImportTitleCancel(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 DeleteTitleContent(const IOCtlVRequest& request);
IPCCommandResult DeleteTicket(const IOCtlVRequest& request);
IPCCommandResult DeleteSharedContent(const IOCtlVRequest& request);
IPCCommandResult DeleteContent(const IOCtlVRequest& request);
IPCReply ImportTicket(const IOCtlVRequest& request);
IPCReply ImportTmd(Context& context, const IOCtlVRequest& request);
IPCReply ImportTitleInit(Context& context, const IOCtlVRequest& request);
IPCReply ImportContentBegin(Context& context, const IOCtlVRequest& request);
IPCReply ImportContentData(Context& context, const IOCtlVRequest& request);
IPCReply ImportContentEnd(Context& context, const IOCtlVRequest& request);
IPCReply ImportTitleDone(Context& context, const IOCtlVRequest& request);
IPCReply ImportTitleCancel(Context& context, const IOCtlVRequest& request);
IPCReply ExportTitleInit(Context& context, const IOCtlVRequest& request);
IPCReply ExportContentBegin(Context& context, const IOCtlVRequest& request);
IPCReply ExportContentData(Context& context, const IOCtlVRequest& request);
IPCReply ExportContentEnd(Context& context, const IOCtlVRequest& request);
IPCReply ExportTitleDone(Context& context, const IOCtlVRequest& request);
IPCReply DeleteTitle(const IOCtlVRequest& request);
IPCReply DeleteTitleContent(const IOCtlVRequest& request);
IPCReply DeleteTicket(const IOCtlVRequest& request);
IPCReply DeleteSharedContent(const IOCtlVRequest& request);
IPCReply DeleteContent(const IOCtlVRequest& request);
// Device identity and encryption
IPCCommandResult GetDeviceId(const IOCtlVRequest& request);
IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request);
IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request);
IPCCommandResult Sign(const IOCtlVRequest& request);
IPCCommandResult VerifySign(const IOCtlVRequest& request);
IPCCommandResult Encrypt(u32 uid, const IOCtlVRequest& request);
IPCCommandResult Decrypt(u32 uid, const IOCtlVRequest& request);
IPCReply GetDeviceId(const IOCtlVRequest& request);
IPCReply GetDeviceCertificate(const IOCtlVRequest& request);
IPCReply CheckKoreaRegion(const IOCtlVRequest& request);
IPCReply Sign(const IOCtlVRequest& request);
IPCReply VerifySign(const IOCtlVRequest& request);
IPCReply Encrypt(u32 uid, const IOCtlVRequest& request);
IPCReply Decrypt(u32 uid, const IOCtlVRequest& request);
// Misc
IPCCommandResult SetUID(u32 uid, const IOCtlVRequest& request);
IPCCommandResult GetTitleDirectory(const IOCtlVRequest& request);
IPCCommandResult GetTitleId(const IOCtlVRequest& request);
IPCCommandResult GetConsumption(const IOCtlVRequest& request);
IPCCommandResult Launch(const IOCtlVRequest& request);
IPCCommandResult LaunchBC(const IOCtlVRequest& request);
IPCCommandResult DIVerify(const IOCtlVRequest& request);
IPCCommandResult SetUpStreamKey(const Context& context, const IOCtlVRequest& request);
IPCCommandResult DeleteStreamKey(const IOCtlVRequest& request);
IPCReply SetUID(u32 uid, const IOCtlVRequest& request);
IPCReply GetTitleDirectory(const IOCtlVRequest& request);
IPCReply GetTitleId(const IOCtlVRequest& request);
IPCReply GetConsumption(const IOCtlVRequest& request);
std::optional<IPCReply> Launch(const IOCtlVRequest& request);
std::optional<IPCReply> LaunchBC(const IOCtlVRequest& request);
IPCReply DIVerify(const IOCtlVRequest& request);
IPCReply SetUpStreamKey(const Context& context, const IOCtlVRequest& request);
IPCReply DeleteStreamKey(const IOCtlVRequest& request);
// Title contents
IPCCommandResult OpenActiveTitleContent(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);
IPCReply OpenActiveTitleContent(u32 uid, const IOCtlVRequest& request);
IPCReply OpenContent(u32 uid, const IOCtlVRequest& request);
IPCReply ReadContent(u32 uid, const IOCtlVRequest& request);
IPCReply CloseContent(u32 uid, const IOCtlVRequest& request);
IPCReply SeekContent(u32 uid, const IOCtlVRequest& request);
// Title information
IPCCommandResult GetTitleCount(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCCommandResult GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request);
IPCCommandResult GetOwnedTitles(const IOCtlVRequest& request);
IPCCommandResult GetTitleCount(const IOCtlVRequest& request);
IPCCommandResult GetTitles(const IOCtlVRequest& request);
IPCCommandResult GetBoot2Version(const IOCtlVRequest& request);
IPCCommandResult GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCCommandResult GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCCommandResult GetStoredContentsCount(const IOCtlVRequest& request);
IPCCommandResult GetStoredContents(const IOCtlVRequest& request);
IPCCommandResult GetTMDStoredContentsCount(const IOCtlVRequest& request);
IPCCommandResult GetTMDStoredContents(const IOCtlVRequest& request);
IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request);
IPCCommandResult GetStoredTMD(const IOCtlVRequest& request);
IPCCommandResult GetSharedContentsCount(const IOCtlVRequest& request) const;
IPCCommandResult GetSharedContents(const IOCtlVRequest& request) const;
IPCReply GetTitleCount(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCReply GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request);
IPCReply GetOwnedTitleCount(const IOCtlVRequest& request);
IPCReply GetOwnedTitles(const IOCtlVRequest& request);
IPCReply GetTitleCount(const IOCtlVRequest& request);
IPCReply GetTitles(const IOCtlVRequest& request);
IPCReply GetBoot2Version(const IOCtlVRequest& request);
IPCReply GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCReply GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request);
IPCReply GetStoredContentsCount(const IOCtlVRequest& request);
IPCReply GetStoredContents(const IOCtlVRequest& request);
IPCReply GetTMDStoredContentsCount(const IOCtlVRequest& request);
IPCReply GetTMDStoredContents(const IOCtlVRequest& request);
IPCReply GetStoredTMDSize(const IOCtlVRequest& request);
IPCReply GetStoredTMD(const IOCtlVRequest& request);
IPCReply GetSharedContentsCount(const IOCtlVRequest& request) const;
IPCReply GetSharedContents(const IOCtlVRequest& request) const;
// Views for tickets and TMDs
IPCCommandResult GetTicketViewCount(const IOCtlVRequest& request);
IPCCommandResult GetTicketViews(const IOCtlVRequest& request);
IPCCommandResult GetV0TicketFromView(const IOCtlVRequest& request);
IPCCommandResult GetTicketSizeFromView(const IOCtlVRequest& request);
IPCCommandResult GetTicketFromView(const IOCtlVRequest& request);
IPCCommandResult GetTMDViewSize(const IOCtlVRequest& request);
IPCCommandResult GetTMDViews(const IOCtlVRequest& request);
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDViewSize(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDView(const IOCtlVRequest& request);
IPCCommandResult DIGetTMDSize(const IOCtlVRequest& request);
IPCCommandResult DIGetTMD(const IOCtlVRequest& request);
IPCReply GetTicketViewCount(const IOCtlVRequest& request);
IPCReply GetTicketViews(const IOCtlVRequest& request);
IPCReply GetV0TicketFromView(const IOCtlVRequest& request);
IPCReply GetTicketSizeFromView(const IOCtlVRequest& request);
IPCReply GetTicketFromView(const IOCtlVRequest& request);
IPCReply GetTMDViewSize(const IOCtlVRequest& request);
IPCReply GetTMDViews(const IOCtlVRequest& request);
IPCReply DIGetTicketView(const IOCtlVRequest& request);
IPCReply DIGetTMDViewSize(const IOCtlVRequest& request);
IPCReply DIGetTMDView(const IOCtlVRequest& request);
IPCReply DIGetTMDSize(const IOCtlVRequest& request);
IPCReply DIGetTMD(const IOCtlVRequest& request);
ContextArray::iterator FindActiveContext(s32 fd);
ContextArray::iterator FindInactiveContext();

View File

@ -27,23 +27,23 @@ ReturnCode ESDevice::GetDeviceId(u32* device_id) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::GetDeviceId(const IOCtlVRequest& request)
IPCReply ESDevice::GetDeviceId(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 device_id;
const ReturnCode ret = GetDeviceId(&device_id);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
Memory::Write_U32(device_id, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address);
@ -54,13 +54,13 @@ IPCCommandResult ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
// TODO: Check whether the active title is allowed to encrypt.
const ReturnCode ret = m_ios.GetIOSC().Encrypt(keyIndex, iv, source, size, destination, PID_ES);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address);
@ -71,38 +71,38 @@ IPCCommandResult ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
// TODO: Check whether the active title is allowed to decrypt.
const ReturnCode ret = m_ios.GetIOSC().Decrypt(keyIndex, iv, source, size, destination, PID_ES);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::CheckKoreaRegion(const IOCtlVRequest& request)
IPCReply ESDevice::CheckKoreaRegion(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// note by DacoTaco : name is unknown, I just tried to name it SOMETHING.
// IOS70 has this to let system menu 4.2 check if the console is region changed. it returns
// -1017
// if the IOS didn't find the Korean keys and 0 if it does. 0 leads to a error 003
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
IPCCommandResult ESDevice::GetDeviceCertificate(const IOCtlVRequest& request)
IPCReply ESDevice::GetDeviceCertificate(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 0x180)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETDEVICECERT");
const IOS::CertECC cert = m_ios.GetIOSC().GetDeviceCertificate();
Memory::CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::Sign(const IOCtlVRequest& request)
IPCReply ESDevice::Sign(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 2))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_SIGN");
u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
@ -111,10 +111,10 @@ IPCCommandResult ESDevice::Sign(const IOCtlVRequest& request)
u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
m_ios.GetIOSC().Sign(sig_out, ap_cert_out, m_title_context.tmd.GetTitleId(), data, data_size);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u8>& ecc_signature,
@ -185,12 +185,12 @@ ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::VerifySign(const IOCtlVRequest& request)
IPCReply ESDevice::VerifySign(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (request.in_vectors[1].size != sizeof(Common::ec::Signature))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> hash(request.in_vectors[0].size);
Memory::CopyFromEmu(hash.data(), request.in_vectors[0].address, hash.size());
@ -201,6 +201,6 @@ IPCCommandResult ESDevice::VerifySign(const IOCtlVRequest& request)
std::vector<u8> certs(request.in_vectors[2].size);
Memory::CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());
return GetDefaultReply(VerifySign(hash, ecc_signature, certs));
return IPCReply(VerifySign(hash, ecc_signature, certs));
}
} // namespace IOS::HLE

View File

@ -46,13 +46,13 @@ s32 ESDevice::OpenContent(const ES::TMDReader& tmd, u16 content_index, u32 uid)
return FS_EFDEXHAUSTED;
}
IPCCommandResult ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0) || request.in_vectors[0].size != sizeof(u64) ||
request.in_vectors[1].size != sizeof(ES::TicketView) ||
request.in_vectors[2].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
@ -61,27 +61,27 @@ IPCCommandResult ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
const auto tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetDefaultReply(OpenContent(tmd, content_index, uid));
return IPCReply(OpenContent(tmd, content_index, uid));
}
IPCCommandResult ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& request)
IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 content_index = Memory::Read_U32(request.in_vectors[0].address);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
ES::UIDSys uid_map{m_ios.GetFS()};
const u32 uid = uid_map.GetOrInsertUIDForTitle(m_title_context.tmd.GetTitleId());
if (caller_uid != 0 && caller_uid != uid)
return GetDefaultReply(ES_EACCES);
return IPCReply(ES_EACCES);
return GetDefaultReply(OpenContent(m_title_context.tmd, content_index, caller_uid));
return IPCReply(OpenContent(m_title_context.tmd, content_index, caller_uid));
}
s32 ESDevice::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid)
@ -99,16 +99,16 @@ s32 ESDevice::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid)
return result.Succeeded() ? *result : FS::ConvertResult(result.Error());
}
IPCCommandResult ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
const u32 size = request.io_vectors[0].size;
const u32 addr = request.io_vectors[0].address;
return GetDefaultReply(ReadContent(cfd, Memory::GetPointer(addr), size, uid));
return IPCReply(ReadContent(cfd, Memory::GetPointer(addr), size, uid));
}
ReturnCode ESDevice::CloseContent(u32 cfd, u32 uid)
@ -128,13 +128,13 @@ ReturnCode ESDevice::CloseContent(u32 cfd, u32 uid)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::CloseContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::CloseContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(CloseContent(cfd, uid));
return IPCReply(CloseContent(cfd, uid));
}
s32 ESDevice::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid)
@ -152,15 +152,15 @@ s32 ESDevice::SeekContent(u32 cfd, u32 offset, SeekMode mode, u32 uid)
return result.Succeeded() ? *result : FS::ConvertResult(result.Error());
}
IPCCommandResult ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
const u32 offset = Memory::Read_U32(request.in_vectors[1].address);
const SeekMode mode = static_cast<SeekMode>(Memory::Read_U32(request.in_vectors[2].address));
return GetDefaultReply(SeekContent(cfd, offset, mode, uid));
return IPCReply(SeekContent(cfd, offset, mode, uid));
}
} // namespace IOS::HLE

View File

@ -16,31 +16,30 @@ namespace IOS::HLE
{
// Used by the GetStoredContents ioctlvs. This assumes that the first output vector
// is used for the content count (u32).
IPCCommandResult ESDevice::GetStoredContentsCount(const ES::TMDReader& tmd,
const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlVRequest& request)
{
if (request.io_vectors[0].size != sizeof(u32) || !tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u16 num_contents = static_cast<u16>(GetStoredContentsFromTMD(tmd).size());
Memory::Write_U32(num_contents, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetStoredContentsCount ({:#x}): {} content(s) for {:016x}",
request.request, num_contents, tmd.GetTitleId());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
// Used by the GetStoredContents ioctlvs. This assumes that the second input vector is used
// for the content count and the output vector is used to store a list of content IDs (u32s).
IPCCommandResult ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVRequest& request)
{
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (request.in_vectors[1].size != sizeof(u32) ||
request.io_vectors[0].size != Memory::Read_U32(request.in_vectors[1].address) * sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const auto contents = GetStoredContentsFromTMD(tmd);
@ -48,82 +47,81 @@ IPCCommandResult ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOC
for (u32 i = 0; i < std::min(static_cast<u32>(contents.size()), max_content_count); ++i)
Memory::Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetStoredContentsCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContentsCount(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u64))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetStoredContentsCount(tmd, request);
}
IPCCommandResult ESDevice::GetStoredContents(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredContents(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) || request.in_vectors[0].size != sizeof(u64))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
return GetStoredContents(tmd, request);
}
IPCCommandResult ESDevice::GetTMDStoredContentsCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDStoredContentsCount(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
return GetStoredContentsCount(ES::TMDReader{std::move(tmd_bytes)}, request);
}
IPCCommandResult ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> cert_store;
ReturnCode ret = ReadCertStore(&cert_store);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
ret = VerifyContainer(VerifyContainerType::TMD, VerifyMode::UpdateCertStore, tmd, cert_store);
if (ret != IPC_SUCCESS)
return GetDefaultReply(ret);
return IPCReply(ret);
return GetStoredContents(tmd, request);
}
IPCCommandResult ESDevice::GetTitleCount(const std::vector<u64>& titles,
const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleCount(const std::vector<u64>& titles, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request)
IPCReply ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const size_t max_count = Memory::Read_U32(request.in_vectors[0].address);
for (size_t i = 0; i < std::min(max_count, titles.size()); i++)
@ -131,112 +129,112 @@ IPCCommandResult ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtl
Memory::Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * sizeof(u64));
INFO_LOG_FMT(IOS_ES, " title {:016x}", titles[i]);
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTitleCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitleCount(const IOCtlVRequest& request)
{
const std::vector<u64> titles = GetInstalledTitles();
INFO_LOG_FMT(IOS_ES, "GetTitleCount: {} titles", titles.size());
return GetTitleCount(titles, request);
}
IPCCommandResult ESDevice::GetTitles(const IOCtlVRequest& request)
IPCReply ESDevice::GetTitles(const IOCtlVRequest& request)
{
return GetTitles(GetInstalledTitles(), request);
}
IPCCommandResult ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
const u32 tmd_size = static_cast<u32>(tmd.GetBytes().size());
Memory::Write_U32(tmd_size, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetStoredTMDSize: {} bytes for {:016x}", tmd_size, title_id);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetStoredTMD(const IOCtlVRequest& request)
IPCReply ESDevice::GetStoredTMD(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
// TODO: actually use this param in when writing to the outbuffer :/
const u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address);
const std::vector<u8>& raw_tmd = tmd.GetBytes();
if (raw_tmd.size() != request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
INFO_LOG_FMT(IOS_ES, "GetStoredTMD: title {:016x} (buffer size: {})", title_id, MaxCount);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetOwnedTitleCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetOwnedTitleCount(const IOCtlVRequest& request)
{
const std::vector<u64> titles = GetTitlesWithTickets();
INFO_LOG_FMT(IOS_ES, "GetOwnedTitleCount: {} titles", titles.size());
return GetTitleCount(titles, request);
}
IPCCommandResult ESDevice::GetOwnedTitles(const IOCtlVRequest& request)
IPCReply ESDevice::GetOwnedTitles(const IOCtlVRequest& request)
{
return GetTitles(GetTitlesWithTickets(), request);
}
IPCCommandResult ESDevice::GetBoot2Version(const IOCtlVRequest& request)
IPCReply ESDevice::GetBoot2Version(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");
// as of 26/02/2012, this was latest bootmii version
Memory::Write_U32(4, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetSharedContentsCount(const IOCtlVRequest& request) const
IPCReply ESDevice::GetSharedContentsCount(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 count = GetSharedContentsCount();
Memory::Write_U32(count, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetSharedContentsCount: {} contents", count);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetSharedContents(const IOCtlVRequest& request) const
IPCReply ESDevice::GetSharedContents(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 max_count = Memory::Read_U32(request.in_vectors[0].address);
if (request.io_vectors[0].size != 20 * max_count)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const std::vector<std::array<u8, 20>> hashes = GetSharedContents();
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
Memory::CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
INFO_LOG_FMT(IOS_ES, "GetSharedContents: {} contents ({} requested)", count, max_count);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE

View File

@ -93,16 +93,16 @@ ReturnCode ESDevice::ImportTicket(const std::vector<u8>& ticket_bytes,
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTicket(const IOCtlVRequest& request)
IPCReply ESDevice::ImportTicket(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
std::vector<u8> cert_chain(request.in_vectors[1].size);
Memory::CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
return GetDefaultReply(ImportTicket(bytes, cert_chain));
return IPCReply(ImportTicket(bytes, cert_chain));
}
constexpr std::array<u8, 16> NULL_KEY{};
@ -180,18 +180,18 @@ ReturnCode ESDevice::ImportTmd(Context& context, const std::vector<u8>& tmd_byte
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTmd(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTmd(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
return GetDefaultReply(ImportTmd(context, tmd, m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
return IPCReply(ImportTmd(context, tmd, m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
}
static ReturnCode InitTitleImportKey(const std::vector<u8>& ticket_bytes, IOSC& iosc,
@ -266,19 +266,19 @@ ReturnCode ESDevice::ImportTitleInit(Context& context, const std::vector<u8>& tm
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTitleInit(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTitleInit(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(4, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> tmd(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
std::vector<u8> certs(request.in_vectors[1].size);
Memory::CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
return GetDefaultReply(ImportTitleInit(context, tmd, certs));
return IPCReply(ImportTitleInit(context, tmd, certs));
}
ReturnCode ESDevice::ImportContentBegin(Context& context, u64 title_id, u32 content_id)
@ -324,14 +324,14 @@ ReturnCode ESDevice::ImportContentBegin(Context& context, u64 title_id, u32 cont
return static_cast<ReturnCode>(content_fd);
}
IPCCommandResult ESDevice::ImportContentBegin(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportContentBegin(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
return GetDefaultReply(ImportContentBegin(context, title_id, content_id));
return IPCReply(ImportContentBegin(context, title_id, content_id));
}
ReturnCode ESDevice::ImportContentData(Context& context, u32 content_fd, const u8* data,
@ -343,15 +343,14 @@ ReturnCode ESDevice::ImportContentData(Context& context, u32 content_fd, const u
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportContentData(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportContentData(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
return GetDefaultReply(
ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
return IPCReply(ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
}
static bool CheckIfContentHashMatches(const std::vector<u8>& content, const ES::Content& info)
@ -429,13 +428,13 @@ ReturnCode ESDevice::ImportContentEnd(Context& context, u32 content_fd)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportContentEnd(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportContentEnd(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(ImportContentEnd(context, content_fd));
return IPCReply(ImportContentEnd(context, content_fd));
}
static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
@ -492,12 +491,12 @@ ReturnCode ESDevice::ImportTitleDone(Context& context)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTitleDone(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTitleDone(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
return GetDefaultReply(ImportTitleDone(context));
return IPCReply(ImportTitleDone(context));
}
ReturnCode ESDevice::ImportTitleCancel(Context& context)
@ -518,12 +517,12 @@ ReturnCode ESDevice::ImportTitleCancel(Context& context)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ImportTitleCancel(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ImportTitleCancel(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 0))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
return GetDefaultReply(ImportTitleCancel(context));
return IPCReply(ImportTitleCancel(context));
}
static bool CanDeleteTitle(u64 title_id)
@ -541,13 +540,13 @@ ReturnCode ESDevice::DeleteTitle(u64 title_id)
return FS::ConvertResult(m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, title_dir));
}
IPCCommandResult ESDevice::DeleteTitle(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteTitle(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
return GetDefaultReply(DeleteTitle(title_id));
return IPCReply(DeleteTitle(title_id));
}
ReturnCode ESDevice::DeleteTicket(const u8* ticket_view)
@ -590,14 +589,14 @@ ReturnCode ESDevice::DeleteTicket(const u8* ticket_view)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::DeleteTicket(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteTicket(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) ||
request.in_vectors[0].size != sizeof(ES::TicketView))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
return GetDefaultReply(DeleteTicket(Memory::GetPointer(request.in_vectors[0].address)));
return IPCReply(DeleteTicket(Memory::GetPointer(request.in_vectors[0].address)));
}
ReturnCode ESDevice::DeleteTitleContent(u64 title_id) const
@ -619,11 +618,11 @@ ReturnCode ESDevice::DeleteTitleContent(u64 title_id) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::DeleteTitleContent(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteTitleContent(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
return GetDefaultReply(ES_EINVAL);
return GetDefaultReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));
return IPCReply(ES_EINVAL);
return IPCReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));
}
ReturnCode ESDevice::DeleteContent(u64 title_id, u32 content_id) const
@ -644,15 +643,15 @@ ReturnCode ESDevice::DeleteContent(u64 title_id, u32 content_id) const
return FS::ConvertResult(m_ios.GetFS()->Delete(PID_KERNEL, PID_KERNEL, path));
}
IPCCommandResult ESDevice::DeleteContent(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteContent(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != sizeof(u64) ||
request.in_vectors[1].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
return GetDefaultReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address),
Memory::Read_U32(request.in_vectors[1].address)));
return IPCReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address),
Memory::Read_U32(request.in_vectors[1].address)));
}
ReturnCode ESDevice::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u32 tmd_size,
@ -684,18 +683,18 @@ ReturnCode ESDevice::ExportTitleInit(Context& context, u64 title_id, u8* tmd_byt
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ExportTitleInit(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportTitleInit(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u8* tmd_bytes = Memory::GetPointer(request.io_vectors[0].address);
const u32 tmd_size = request.io_vectors[0].size;
return GetDefaultReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
return IPCReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
}
ReturnCode ESDevice::ExportContentBegin(Context& context, u64 title_id, u32 content_id)
@ -729,16 +728,16 @@ ReturnCode ESDevice::ExportContentBegin(Context& context, u64 title_id, u32 cont
return static_cast<ReturnCode>(ret);
}
IPCCommandResult ESDevice::ExportContentBegin(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportContentBegin(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != 8 ||
request.in_vectors[1].size != 4)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
return GetDefaultReply(ExportContentBegin(context, title_id, content_id));
return IPCReply(ExportContentBegin(context, title_id, content_id));
}
ReturnCode ESDevice::ExportContentData(Context& context, u32 content_fd, u8* data, u32 data_size)
@ -775,19 +774,19 @@ ReturnCode ESDevice::ExportContentData(Context& context, u32 content_fd, u8* dat
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ExportContentData(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportContentData(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 4 ||
request.io_vectors[0].size == 0)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
u8* data = Memory::GetPointer(request.io_vectors[0].address);
const u32 bytes_to_read = request.io_vectors[0].size;
return GetDefaultReply(ExportContentData(context, content_fd, data, bytes_to_read));
return IPCReply(ExportContentData(context, content_fd, data, bytes_to_read));
}
ReturnCode ESDevice::ExportContentEnd(Context& context, u32 content_fd)
@ -797,13 +796,13 @@ ReturnCode ESDevice::ExportContentEnd(Context& context, u32 content_fd)
return CloseContent(content_fd, 0);
}
IPCCommandResult ESDevice::ExportContentEnd(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportContentEnd(Context& context, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
return GetDefaultReply(ExportContentEnd(context, content_fd));
return IPCReply(ExportContentEnd(context, content_fd));
}
ReturnCode ESDevice::ExportTitleDone(Context& context)
@ -812,9 +811,9 @@ ReturnCode ESDevice::ExportTitleDone(Context& context)
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& request)
IPCReply ESDevice::ExportTitleDone(Context& context, const IOCtlVRequest& request)
{
return GetDefaultReply(ExportTitleDone(context));
return IPCReply(ExportTitleDone(context));
}
ReturnCode ESDevice::DeleteSharedContent(const std::array<u8, 20>& sha1) const
@ -854,12 +853,12 @@ ReturnCode ESDevice::DeleteSharedContent(const std::array<u8, 20>& sha1) const
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::DeleteSharedContent(const IOCtlVRequest& request)
IPCReply ESDevice::DeleteSharedContent(const IOCtlVRequest& request)
{
std::array<u8, 20> sha1;
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sha1.size())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);
return GetDefaultReply(DeleteSharedContent(sha1));
return IPCReply(DeleteSharedContent(sha1));
}
} // namespace IOS::HLE

View File

@ -36,10 +36,10 @@ static bool ShouldReturnFakeViewsForIOSes(u64 title_id, const TitleContext& cont
(ios && SConfig::GetInstance().m_disc_booted_from_game_list && disc_title);
}
IPCCommandResult ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
@ -61,13 +61,13 @@ IPCCommandResult ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
view_count);
Memory::Write_U32(view_count, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTicketViews(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const u32 maxViews = Memory::Read_U32(request.in_vectors[1].address);
@ -96,7 +96,7 @@ IPCCommandResult ESDevice::GetTicketViews(const IOCtlVRequest& request)
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETVIEWS for titleID: {:016x} (MaxViews = {})", TitleID, maxViews);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
ReturnCode ESDevice::GetV0TicketFromView(const u8* ticket_view, u8* ticket) const
@ -157,106 +157,106 @@ ReturnCode ESDevice::GetTicketFromView(const u8* ticket_view, u8* ticket, u32* t
return IPC_SUCCESS;
}
IPCCommandResult ESDevice::GetV0TicketFromView(const IOCtlVRequest& request)
IPCReply ESDevice::GetV0TicketFromView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
request.io_vectors[0].size != sizeof(ES::Ticket))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
return GetDefaultReply(GetV0TicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address)));
return IPCReply(GetV0TicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address)));
}
IPCCommandResult ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
{
u32 ticket_size = 0;
if (!request.HasNumberOfValidVectors(1, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
request.io_vectors[0].size != sizeof(ticket_size))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const ReturnCode ret =
GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address), nullptr, &ticket_size);
Memory::Write_U32(ticket_size, request.io_vectors[0].address);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult ESDevice::GetTicketFromView(const IOCtlVRequest& request)
IPCReply ESDevice::GetTicketFromView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TicketView) ||
request.in_vectors[1].size != sizeof(u32))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
u32 ticket_size = Memory::Read_U32(request.in_vectors[1].address);
if (ticket_size != request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
return GetDefaultReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address),
&ticket_size));
return IPCReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address),
&ticket_size));
}
IPCCommandResult ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(TitleID);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
const u32 view_size = static_cast<u32>(tmd.GetRawView().size());
Memory::Write_U32(view_size, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetTMDViewSize: {} bytes for title {:016x}", view_size, TitleID);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::GetTMDViews(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TMDHeader::title_id) ||
request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
return IPCReply(FS_ENOENT);
const std::vector<u8> raw_view = tmd.GetRawView();
if (request.io_vectors[0].size < raw_view.size())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, raw_view.data(), raw_view.size());
INFO_LOG_FMT(IOS_ES, "GetTMDView: {} bytes for title {:016x}", raw_view.size(), title_id);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Sanity check the TMD size.
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const bool has_tmd = request.in_vectors[0].size != 0;
size_t tmd_view_size = 0;
@ -270,7 +270,7 @@ IPCCommandResult ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
// Yes, this returns -1017, not ES_INVALID_TMD.
// IOS simply checks whether the TMD has all required content entries.
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view_size = tmd.GetRawView().size();
}
@ -278,29 +278,29 @@ IPCCommandResult ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
{
// If no TMD was passed in and no title is active, IOS returns -1017.
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view_size = m_title_context.tmd.GetRawView().size();
}
Memory::Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMDView(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 1))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Sanity check the TMD size.
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
// Check whether the TMD view size is consistent.
if (request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const bool has_tmd = request.in_vectors[0].size != 0;
@ -313,7 +313,7 @@ IPCCommandResult ESDevice::DIGetTMDView(const IOCtlVRequest& request)
const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view = tmd.GetRawView();
}
@ -321,31 +321,31 @@ IPCCommandResult ESDevice::DIGetTMDView(const IOCtlVRequest& request)
{
// If no TMD was passed in and no title is active, IOS returns -1017.
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
tmd_view = m_title_context.tmd.GetRawView();
}
if (tmd_view.size() > request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, tmd_view.data(), tmd_view.size());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTicketView(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) ||
request.io_vectors[0].size != sizeof(ES::TicketView))
{
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
}
const bool has_ticket_vector = request.in_vectors[0].size == sizeof(ES::Ticket);
// This ioctlv takes either a signed ticket or no ticket, in which case the ticket size must be 0.
if (!has_ticket_vector && request.in_vectors[0].size != 0)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
std::vector<u8> view;
@ -354,7 +354,7 @@ IPCCommandResult ESDevice::DIGetTicketView(const IOCtlVRequest& request)
if (!has_ticket_vector)
{
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
view = m_title_context.ticket.GetRawTicketView(0);
}
@ -368,40 +368,40 @@ IPCCommandResult ESDevice::DIGetTicketView(const IOCtlVRequest& request)
}
Memory::CopyToEmu(request.io_vectors[0].address, view.data(), view.size());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMDSize(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMDSize(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::Write_U32(static_cast<u32>(m_title_context.tmd.GetBytes().size()),
request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult ESDevice::DIGetTMD(const IOCtlVRequest& request)
IPCReply ESDevice::DIGetTMD(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const u32 tmd_size = Memory::Read_U32(request.in_vectors[0].address);
if (tmd_size != request.io_vectors[0].size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
if (!m_title_context.active)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
const std::vector<u8>& tmd_bytes = m_title_context.tmd.GetBytes();
if (static_cast<u32>(tmd_bytes.size()) > tmd_size)
return GetDefaultReply(ES_EINVAL);
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, tmd_bytes.data(), tmd_bytes.size());
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE

View File

@ -22,10 +22,10 @@ namespace IOS::HLE
{
using namespace IOS::HLE::FS;
static IPCCommandResult GetFSReply(s32 return_value, u64 extra_tb_ticks = 0)
static IPCReply GetFSReply(s32 return_value, u64 extra_tb_ticks = 0)
{
// According to hardware tests, FS takes at least 2700 TB ticks to reply to commands.
return {return_value, true, (2700 + extra_tb_ticks) * SystemTimers::TIMER_RATIO};
return IPCReply{return_value, (2700 + extra_tb_ticks) * SystemTimers::TIMER_RATIO};
}
/// Amount of TB ticks required for a superblock write to complete.
@ -97,13 +97,13 @@ static u64 EstimateFileLookupTicks(const std::string& path, FileLookupMode mode)
///
/// A superblock flush takes a very large amount of time, so other delays are ignored
/// to simplify the implementation as they are insignificant.
static IPCCommandResult GetReplyForSuperblockOperation(ResultCode result)
static IPCReply GetReplyForSuperblockOperation(ResultCode result)
{
const u64 ticks = result == ResultCode::Success ? SUPERBLOCK_WRITE_TICKS : 0;
return GetFSReply(ConvertResult(result), ticks);
}
IPCCommandResult FSDevice::Open(const OpenRequest& request)
std::optional<IPCReply> FSDevice::Open(const OpenRequest& request)
{
if (m_fd_map.size() >= 16)
return GetFSReply(ConvertResult(ResultCode::NoFreeHandle));
@ -130,7 +130,7 @@ IPCCommandResult FSDevice::Open(const OpenRequest& request)
return GetFSReply(IPC_SUCCESS, ticks);
}
IPCCommandResult FSDevice::Close(u32 fd)
std::optional<IPCReply> FSDevice::Close(u32 fd)
{
u64 ticks = 0;
if (m_fd_map[fd].fs_fd != INVALID_FD)
@ -229,7 +229,7 @@ bool FSDevice::HasCacheForFile(u32 fd, u32 offset) const
return m_cache_fd == fd && m_cache_chain_index == chain_index;
}
IPCCommandResult FSDevice::Read(const ReadWriteRequest& request)
std::optional<IPCReply> FSDevice::Read(const ReadWriteRequest& request)
{
const Handle& handle = m_fd_map[request.fd];
if (handle.fs_fd == INVALID_FD)
@ -247,7 +247,7 @@ IPCCommandResult FSDevice::Read(const ReadWriteRequest& request)
return GetFSReply(*result, ticks);
}
IPCCommandResult FSDevice::Write(const ReadWriteRequest& request)
std::optional<IPCReply> FSDevice::Write(const ReadWriteRequest& request)
{
const Handle& handle = m_fd_map[request.fd];
if (handle.fs_fd == INVALID_FD)
@ -265,7 +265,7 @@ IPCCommandResult FSDevice::Write(const ReadWriteRequest& request)
return GetFSReply(*result, ticks);
}
IPCCommandResult FSDevice::Seek(const SeekRequest& request)
std::optional<IPCReply> FSDevice::Seek(const SeekRequest& request)
{
const Handle& handle = m_fd_map[request.fd];
if (handle.fs_fd == INVALID_FD)
@ -318,11 +318,11 @@ static Result<T> GetParams(const IOCtlRequest& request)
return params;
}
IPCCommandResult FSDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> FSDevice::IOCtl(const IOCtlRequest& request)
{
const auto it = m_fd_map.find(request.fd);
if (it == m_fd_map.end())
return GetDefaultReply(ConvertResult(ResultCode::Invalid));
return IPCReply(ConvertResult(ResultCode::Invalid));
switch (request.request)
{
@ -353,11 +353,11 @@ IPCCommandResult FSDevice::IOCtl(const IOCtlRequest& request)
}
}
IPCCommandResult FSDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> FSDevice::IOCtlV(const IOCtlVRequest& request)
{
const auto it = m_fd_map.find(request.fd);
if (it == m_fd_map.end())
return GetDefaultReply(ConvertResult(ResultCode::Invalid));
return IPCReply(ConvertResult(ResultCode::Invalid));
switch (request.request)
{
@ -370,7 +370,7 @@ IPCCommandResult FSDevice::IOCtlV(const IOCtlVRequest& request)
}
}
IPCCommandResult FSDevice::Format(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::Format(const Handle& handle, const IOCtlRequest& request)
{
if (handle.uid != 0)
return GetFSReply(ConvertResult(ResultCode::AccessDenied));
@ -379,7 +379,7 @@ IPCCommandResult FSDevice::Format(const Handle& handle, const IOCtlRequest& requ
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_out_size < sizeof(ISFSNandStats))
return GetFSReply(ConvertResult(ResultCode::Invalid));
@ -387,7 +387,7 @@ IPCCommandResult FSDevice::GetStats(const Handle& handle, const IOCtlRequest& re
const Result<NandStats> stats = m_ios.GetFS()->GetNandStats();
LogResult(stats, "GetNandStats");
if (!stats)
return GetDefaultReply(ConvertResult(stats.Error()));
return IPCReply(ConvertResult(stats.Error()));
ISFSNandStats out;
out.cluster_size = stats->cluster_size;
@ -398,10 +398,10 @@ IPCCommandResult FSDevice::GetStats(const Handle& handle, const IOCtlRequest& re
out.free_inodes = stats->free_inodes;
out.used_inodes = stats->used_inodes;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@ -413,7 +413,7 @@ IPCCommandResult FSDevice::CreateDirectory(const Handle& handle, const IOCtlRequ
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& request)
IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& request)
{
if (request.in_vectors.empty() || request.in_vectors.size() != request.io_vectors.size() ||
request.in_vectors.size() > 2 || request.in_vectors[0].size != 64)
@ -467,7 +467,7 @@ IPCCommandResult FSDevice::ReadDirectory(const Handle& handle, const IOCtlVReque
return GetFSReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@ -479,7 +479,7 @@ IPCCommandResult FSDevice::SetAttribute(const Handle& handle, const IOCtlRequest
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams))
return GetFSReply(ConvertResult(ResultCode::Invalid));
@ -503,7 +503,7 @@ IPCCommandResult FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest
return GetFSReply(IPC_SUCCESS, ticks);
}
IPCCommandResult FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_in_size < 64)
return GetFSReply(ConvertResult(ResultCode::Invalid));
@ -514,7 +514,7 @@ IPCCommandResult FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest&
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_in_size < 64 * 2)
return GetFSReply(ConvertResult(ResultCode::Invalid));
@ -526,7 +526,7 @@ IPCCommandResult FSDevice::RenameFile(const Handle& handle, const IOCtlRequest&
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::CreateFile(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@ -538,7 +538,7 @@ IPCCommandResult FSDevice::CreateFile(const Handle& handle, const IOCtlRequest&
return GetReplyForSuperblockOperation(result);
}
IPCCommandResult FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::SetFileVersionControl(const Handle& handle, const IOCtlRequest& request)
{
const auto params = GetParams<ISFSParams>(request);
if (!params)
@ -550,7 +550,7 @@ IPCCommandResult FSDevice::SetFileVersionControl(const Handle& handle, const IOC
return GetFSReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& request)
{
if (request.buffer_out_size < 8 || handle.fs_fd == INVALID_FD)
return GetFSReply(ConvertResult(ResultCode::Invalid));
@ -558,16 +558,16 @@ IPCCommandResult FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest
const Result<FileStatus> status = m_ios.GetFS()->GetFileStatus(handle.fs_fd);
LogResult(status, "GetFileStatus({})", handle.name.data());
if (!status)
return GetDefaultReply(ConvertResult(status.Error()));
return IPCReply(ConvertResult(status.Error()));
ISFSFileStats out;
out.size = status->size;
out.seek_position = status->offset;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 2) || request.in_vectors[0].size != 64 ||
request.io_vectors[0].size != 4 || request.io_vectors[1].size != 4)
@ -586,7 +586,7 @@ IPCCommandResult FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& r
return GetFSReply(IPC_SUCCESS);
}
IPCCommandResult FSDevice::Shutdown(const Handle& handle, const IOCtlRequest& request)
IPCReply FSDevice::Shutdown(const Handle& handle, const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_FS, "Shutdown");
return GetFSReply(IPC_SUCCESS);

View File

@ -26,13 +26,13 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult Read(const ReadWriteRequest& request) override;
IPCCommandResult Write(const ReadWriteRequest& request) override;
IPCCommandResult Seek(const SeekRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> Read(const ReadWriteRequest& request) override;
std::optional<IPCReply> Write(const ReadWriteRequest& request) override;
std::optional<IPCReply> Seek(const SeekRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
private:
struct Handle
@ -62,19 +62,19 @@ private:
ISFS_IOCTL_SHUTDOWN = 13,
};
IPCCommandResult Format(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetStats(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult CreateDirectory(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult ReadDirectory(const Handle& handle, const IOCtlVRequest& request);
IPCCommandResult SetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult DeleteFile(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult RenameFile(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult CreateFile(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult SetFileVersionControl(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetFileStats(const Handle& handle, const IOCtlRequest& request);
IPCCommandResult GetUsage(const Handle& handle, const IOCtlVRequest& request);
IPCCommandResult Shutdown(const Handle& handle, const IOCtlRequest& request);
IPCReply Format(const Handle& handle, const IOCtlRequest& request);
IPCReply GetStats(const Handle& handle, const IOCtlRequest& request);
IPCReply CreateDirectory(const Handle& handle, const IOCtlRequest& request);
IPCReply ReadDirectory(const Handle& handle, const IOCtlVRequest& request);
IPCReply SetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCReply GetAttribute(const Handle& handle, const IOCtlRequest& request);
IPCReply DeleteFile(const Handle& handle, const IOCtlRequest& request);
IPCReply RenameFile(const Handle& handle, const IOCtlRequest& request);
IPCReply CreateFile(const Handle& handle, const IOCtlRequest& request);
IPCReply SetFileVersionControl(const Handle& handle, const IOCtlRequest& request);
IPCReply GetFileStats(const Handle& handle, const IOCtlRequest& request);
IPCReply GetUsage(const Handle& handle, const IOCtlVRequest& request);
IPCReply Shutdown(const Handle& handle, const IOCtlRequest& request);
u64 EstimateTicksForReadWrite(const Handle& handle, const ReadWriteRequest& request);
u64 SimulatePopulateFileCache(u32 fd, u32 offset, u32 file_size);

View File

@ -518,14 +518,14 @@ std::shared_ptr<Device> EmulationKernel::GetDeviceByName(std::string_view device
}
// Returns the FD for the newly opened device (on success) or an error code.
IPCCommandResult Kernel::OpenDevice(OpenRequest& request)
std::optional<IPCReply> Kernel::OpenDevice(OpenRequest& request)
{
const s32 new_fd = GetFreeDeviceID();
INFO_LOG_FMT(IOS, "Opening {} (mode {}, fd {})", request.path, request.flags, new_fd);
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
{
ERROR_LOG_FMT(IOS, "Couldn't get a free fd, too many open files");
return IPCCommandResult{IPC_EMAX, true, 5000 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_EMAX, 5000_tbticks};
}
request.fd = new_fd;
@ -547,22 +547,22 @@ IPCCommandResult Kernel::OpenDevice(OpenRequest& request)
if (!device)
{
ERROR_LOG_FMT(IOS, "Unknown device: {}", request.path);
return {IPC_ENOENT, true, 3700 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_ENOENT, 3700_tbticks};
}
IPCCommandResult result = device->Open(request);
if (result.return_value >= IPC_SUCCESS)
std::optional<IPCReply> result = device->Open(request);
if (result && result->return_value >= IPC_SUCCESS)
{
m_fdmap[new_fd] = device;
result.return_value = new_fd;
result->return_value = new_fd;
}
return result;
}
IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
std::optional<IPCReply> Kernel::HandleIPCCommand(const Request& request)
{
if (request.command < IPC_CMD_OPEN || request.command > IPC_CMD_IOCTLV)
return IPCCommandResult{IPC_EINVAL, true, 978 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_EINVAL, 978_tbticks};
if (request.command == IPC_CMD_OPEN)
{
@ -572,9 +572,9 @@ IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
const auto device = (request.fd < IPC_MAX_FDS) ? m_fdmap[request.fd] : nullptr;
if (!device)
return IPCCommandResult{IPC_EINVAL, true, 550 * SystemTimers::TIMER_RATIO};
return IPCReply{IPC_EINVAL, 550_tbticks};
IPCCommandResult ret;
std::optional<IPCReply> ret;
const u64 wall_time_before = Common::Timer::GetTimeUs();
switch (request.command)
@ -600,7 +600,7 @@ IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
break;
default:
ASSERT_MSG(IOS, false, "Unexpected command: %x", request.command);
ret = IPCCommandResult{IPC_EINVAL, true, 978 * SystemTimers::TIMER_RATIO};
ret = IPCReply{IPC_EINVAL, 978_tbticks};
break;
}
@ -618,18 +618,18 @@ IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
void Kernel::ExecuteIPCCommand(const u32 address)
{
Request request{address};
IPCCommandResult result = HandleIPCCommand(request);
std::optional<IPCReply> result = HandleIPCCommand(request);
if (!result.send_reply)
if (!result)
return;
// Ensure replies happen in order
const s64 ticks_until_last_reply = m_last_reply_time - CoreTiming::GetTicks();
if (ticks_until_last_reply > 0)
result.reply_delay_ticks += ticks_until_last_reply;
m_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
result->reply_delay_ticks += ticks_until_last_reply;
m_last_reply_time = CoreTiming::GetTicks() + result->reply_delay_ticks;
EnqueueIPCReply(request, result.return_value, static_cast<int>(result.reply_delay_ticks));
EnqueueIPCReply(request, result->return_value, result->reply_delay_ticks);
}
// Happens AS SOON AS IPC gets a new pointer!
@ -638,12 +638,11 @@ void Kernel::EnqueueIPCRequest(u32 address)
// Based on hardware tests, IOS takes between 5µs and 10µs to acknowledge an IPC request.
// Console 1: 456 TB ticks before ACK
// Console 2: 658 TB ticks before ACK
CoreTiming::ScheduleEvent(500 * SystemTimers::TIMER_RATIO, s_event_enqueue,
address | ENQUEUE_REQUEST_FLAG);
CoreTiming::ScheduleEvent(500_tbticks, s_event_enqueue, address | ENQUEUE_REQUEST_FLAG);
}
// Called to send a reply to an IOS syscall
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, int cycles_in_future,
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, s64 cycles_in_future,
CoreTiming::FromThread from)
{
Memory::Write_U32(static_cast<u32>(return_value), request.address + 4);
@ -852,4 +851,20 @@ EmulationKernel* GetIOS()
{
return s_ios.get();
}
// Based on a hardware test, a device takes at least ~2700 ticks to reply to an IPC request.
// Depending on how much work a command performs, this can take much longer (10000+)
// especially if the NAND filesystem is accessed.
//
// Because we currently don't emulate timing very accurately, we should not return
// the minimum possible reply time (~960 ticks from the kernel or ~2700 from devices)
// but an average value, otherwise we are going to be much too fast in most cases.
IPCReply::IPCReply(s32 return_value_) : IPCReply(return_value_, 4000_tbticks)
{
}
IPCReply::IPCReply(s32 return_value_, u64 reply_delay_ticks_)
: return_value(return_value_), reply_delay_ticks(reply_delay_ticks_)
{
}
} // namespace IOS::HLE

View File

@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
@ -33,10 +34,14 @@ class ESDevice;
struct Request;
struct OpenRequest;
struct IPCCommandResult
struct IPCReply
{
/// Constructs a reply with an average reply time.
/// Please avoid using this function if more accurate timings are known.
explicit IPCReply(s32 return_value_);
explicit IPCReply(s32 return_value_, u64 reply_delay_ticks_);
s32 return_value;
bool send_reply;
u64 reply_delay_ticks;
};
@ -84,7 +89,7 @@ public:
void SDIO_EventNotify();
void EnqueueIPCRequest(u32 address);
void EnqueueIPCReply(const Request& request, s32 return_value, int cycles_in_future = 0,
void EnqueueIPCReply(const Request& request, s32 return_value, s64 cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
void SetUidForPPC(u32 uid);
@ -102,7 +107,7 @@ protected:
explicit Kernel(u64 title_id);
void ExecuteIPCCommand(u32 address);
IPCCommandResult HandleIPCCommand(const Request& request);
std::optional<IPCReply> HandleIPCCommand(const Request& request);
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
void AddDevice(std::unique_ptr<Device> device);
@ -110,7 +115,7 @@ protected:
void AddStaticDevices();
std::shared_ptr<Device> GetDeviceByName(std::string_view device_name);
s32 GetFreeDeviceID();
IPCCommandResult OpenDevice(OpenRequest& request);
std::optional<IPCReply> OpenDevice(OpenRequest& request);
bool m_is_responsible_for_nand_root = false;
u64 m_title_id = 0;

View File

@ -285,11 +285,11 @@ static DefaultInterface GetSystemDefaultInterfaceOrFallback()
return GetSystemDefaultInterface().value_or(FALLBACK_VALUES);
}
IPCCommandResult NetIPTopDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> NetIPTopDevice::IOCtl(const IOCtlRequest& request)
{
if (Core::WantsDeterminism())
{
return GetDefaultReply(IPC_EACCES);
return IPCReply(IPC_EACCES);
}
switch (request.request)
@ -339,10 +339,10 @@ IPCCommandResult NetIPTopDevice::IOCtl(const IOCtlRequest& request)
break;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult NetIPTopDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> NetIPTopDevice::IOCtlV(const IOCtlVRequest& request)
{
switch (request.request)
{
@ -361,7 +361,7 @@ IPCCommandResult NetIPTopDevice::IOCtlV(const IOCtlVRequest& request)
break;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
void NetIPTopDevice::Update()
@ -369,13 +369,13 @@ void NetIPTopDevice::Update()
WiiSockMan::GetInstance().Update();
}
IPCCommandResult NetIPTopDevice::HandleInitInterfaceRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInitInterfaceRequest(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), Common::Log::IOS_WC24);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request)
{
const u32 af = Memory::Read_U32(request.buffer_in);
const u32 type = Memory::Read_U32(request.buffer_in + 4);
@ -389,20 +389,20 @@ IPCCommandResult NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request
return_value, af, type, prot, request.buffer_in, request.buffer_in_size,
request.buffer_out, request.buffer_out_size);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request)
{
const u32 pf = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
const s32 return_value = sm.NewSocket(pf, SOCK_RAW, IPPROTO_ICMP);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_ICMPSOCKET({:x}) {}", pf, return_value);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
@ -412,24 +412,24 @@ IPCCommandResult NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
INFO_LOG_FMT(IOS_NET, "{}({:x}) {:x}", close_fn, fd, return_value);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleDoSockRequest(const IOCtlRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandleDoSockRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, static_cast<NET_IOCTL>(request.request));
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request)
{
if (request.buffer_in == 0 || request.buffer_in_size < 8)
{
ERROR_LOG_FMT(IOS_NET, "IOCTL_SO_SHUTDOWN = EINVAL, BufferIn: ({:08x}, {})", request.buffer_in,
request.buffer_in_size);
return GetDefaultReply(-SO_EINVAL);
return IPCReply(-SO_EINVAL);
}
const u32 fd = Memory::Read_U32(request.buffer_in);
@ -438,20 +438,20 @@ IPCCommandResult NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& reque
const s32 return_value = sm.ShutdownSocket(fd, how);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_SHUTDOWN(fd={}, how={}) = {}", fd, how, return_value);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
u32 BACKLOG = Memory::Read_U32(request.buffer_in + 0x04);
u32 ret = listen(WiiSockMan::GetInstance().GetHostSocket(fd), BACKLOG);
request.Log(GetDeviceName(), Common::Log::IOS_WC24);
return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false));
return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false));
}
IPCCommandResult NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_out);
u32 level = Memory::Read_U32(request.buffer_out + 4);
@ -481,10 +481,10 @@ IPCCommandResult NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& req
Memory::Write_U32(last_error, request.buffer_out + 0x10);
}
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
IPCCommandResult NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
const u32 level = Memory::Read_U32(request.buffer_in + 4);
@ -508,7 +508,7 @@ IPCCommandResult NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& req
// TODO: bug booto about this, 0x2005 most likely timeout related, default value on Wii is ,
// 0x2001 is most likely tcpnodelay
if (level == 6 && (optname == 0x2005 || optname == 0x2001))
return GetDefaultReply(0);
return IPCReply(0);
// Do the level/optname translation
const int nat_level = MapWiiSockOptLevelToNative(level);
@ -516,10 +516,10 @@ IPCCommandResult NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& req
const int ret = setsockopt(WiiSockMan::GetInstance().GetHostSocket(fd), nat_level, nat_optname,
reinterpret_cast<char*>(optval), optlen);
return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false));
return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false));
}
IPCCommandResult NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
@ -542,10 +542,10 @@ IPCCommandResult NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& re
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
}
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
@ -567,19 +567,19 @@ IPCCommandResult NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& re
}
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_GETPEERNAME({:x})", fd);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult NetIPTopDevice::HandleGetHostIDRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetHostIDRequest(const IOCtlRequest& request)
{
const DefaultInterface interface = GetSystemDefaultInterfaceOrFallback();
const u32 host_ip = Common::swap32(interface.inet);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_GETHOSTID = {}.{}.{}.{}", host_ip >> 24, (host_ip >> 16) & 0xFF,
(host_ip >> 8) & 0xFF, host_ip & 0xFF);
return GetDefaultReply(host_ip);
return IPCReply(host_ip);
}
IPCCommandResult NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
{
const std::string hostname = Memory::GetString(request.buffer_in);
struct hostent* remoteHost = gethostbyname(hostname.c_str());
@ -593,7 +593,7 @@ IPCCommandResult NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& reque
hostname, request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size);
return GetDefaultReply(0);
return IPCReply(0);
}
const auto ip = Common::swap32(reinterpret_cast<u8*>(remoteHost->h_addr_list[0]));
@ -605,17 +605,17 @@ IPCCommandResult NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& reque
hostname, request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size, ip);
return GetDefaultReply(1);
return IPCReply(1);
}
IPCCommandResult NetIPTopDevice::HandleInetPToNRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetPToNRequest(const IOCtlRequest& request)
{
const std::string address = Memory::GetString(request.buffer_in);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_INETPTON (Translating: {})", address);
return GetDefaultReply(inet_pton(address.c_str(), Memory::GetPointer(request.buffer_out + 4)));
return IPCReply(inet_pton(address.c_str(), Memory::GetPointer(request.buffer_out + 4)));
}
IPCCommandResult NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& request)
{
// u32 af = Memory::Read_U32(BufferIn);
// u32 validAddress = Memory::Read_U32(request.buffer_in + 4);
@ -628,15 +628,15 @@ IPCCommandResult NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& reque
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_INETNTOP {}", ip_s);
Memory::CopyToEmu(request.buffer_out, reinterpret_cast<u8*>(ip_s), std::strlen(ip_s));
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
{
WiiSockMan& sm = WiiSockMan::GetInstance();
if (!request.buffer_in || !request.buffer_out)
return GetDefaultReply(-SO_EINVAL);
return IPCReply(-SO_EINVAL);
// Negative timeout indicates wait forever
const s64 timeout = static_cast<s64>(Memory::Read_U64(request.buffer_in));
@ -645,7 +645,7 @@ IPCCommandResult NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
if (nfds == 0 || nfds > WII_SOCKET_FD_MAX)
{
ERROR_LOG_FMT(IOS_NET, "IOCTL_SO_POLL failed: Invalid array size {}, ret={}", nfds, -SO_EINVAL);
return GetDefaultReply(-SO_EINVAL);
return IPCReply(-SO_EINVAL);
}
std::vector<pollfd_t> ufds(nfds);
@ -671,15 +671,15 @@ IPCCommandResult NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
// Prevents blocking emulation on a blocking poll
sm.AddPollCommand({request.address, request.buffer_out, std::move(ufds), timeout});
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest& request)
{
if (request.buffer_out_size != 0x460)
{
ERROR_LOG_FMT(IOS_NET, "Bad buffer size for IOCTL_SO_GETHOSTBYNAME");
return GetDefaultReply(-1);
return IPCReply(-1);
}
const std::string hostname = Memory::GetString(request.buffer_in);
@ -692,7 +692,7 @@ IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest&
request.buffer_out_size);
if (remoteHost == nullptr)
return GetDefaultReply(-1);
return IPCReply(-1);
for (int i = 0; remoteHost->h_aliases[i]; ++i)
{
@ -715,7 +715,7 @@ IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest&
if (name_length > (GETHOSTBYNAME_IP_LIST_OFFSET - GETHOSTBYNAME_STRUCT_SIZE))
{
ERROR_LOG_FMT(IOS_NET, "Hostname too long in IOCTL_SO_GETHOSTBYNAME");
return GetDefaultReply(-1);
return IPCReply(-1);
}
Memory::CopyToEmu(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, remoteHost->h_name,
name_length);
@ -757,16 +757,16 @@ IPCCommandResult NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest&
Memory::Write_U16(AF_INET, request.buffer_out + 8);
Memory::Write_U16(sizeof(u32), request.buffer_out + 10);
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandleICMPCancelRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleICMPCancelRequest(const IOCtlRequest& request)
{
ERROR_LOG_FMT(IOS_NET, "IOCTL_SO_ICMPCANCEL");
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& request)
IPCReply NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& request)
{
const u32 param = Memory::Read_U32(request.in_vectors[0].address);
const u32 param2 = Memory::Read_U32(request.in_vectors[0].address + 4);
@ -777,7 +777,7 @@ IPCCommandResult NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVReques
if (param != 0xfffe)
{
WARN_LOG_FMT(IOS_NET, "GetInterfaceOpt: received invalid request with param0={:08x}", param);
return GetDefaultReply(SO_ERROR_INVALID_REQUEST);
return IPCReply(SO_ERROR_INVALID_REQUEST);
}
if (request.io_vectors[0].size >= 8)
@ -939,26 +939,26 @@ IPCCommandResult NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVReques
break;
}
return GetDefaultReply(0);
return IPCReply(0);
}
IPCCommandResult NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest& request)
{
u32 fd = Memory::Read_U32(request.in_vectors[1].address);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_SENDTO);
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleRecvFromRequest(const IOCtlVRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandleRecvFromRequest(const IOCtlVRequest& request)
{
u32 fd = Memory::Read_U32(request.in_vectors[0].address);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_RECVFROM);
return GetNoReply();
return std::nullopt;
}
IPCCommandResult NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& request)
IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& request)
{
addrinfo hints;
const bool hints_valid = request.in_vectors.size() > 2 && request.in_vectors[2].size;
@ -1044,10 +1044,10 @@ IPCCommandResult NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest
}
request.Dump(GetDeviceName(), Common::Log::IOS_NET, Common::Log::LINFO);
return GetDefaultReply(ret);
return IPCReply(ret);
}
IPCCommandResult NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request)
IPCReply NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request)
{
struct
{
@ -1111,6 +1111,6 @@ IPCCommandResult NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& requ
}
// TODO proper error codes
return GetDefaultReply(0);
return IPCReply(0);
}
} // namespace IOS::HLE

View File

@ -68,36 +68,36 @@ public:
virtual ~NetIPTopDevice();
void DoState(PointerWrap& p) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
void Update() override;
private:
IPCCommandResult HandleInitInterfaceRequest(const IOCtlRequest& request);
IPCCommandResult HandleSocketRequest(const IOCtlRequest& request);
IPCCommandResult HandleICMPSocketRequest(const IOCtlRequest& request);
IPCCommandResult HandleCloseRequest(const IOCtlRequest& request);
IPCCommandResult HandleDoSockRequest(const IOCtlRequest& request);
IPCCommandResult HandleShutdownRequest(const IOCtlRequest& request);
IPCCommandResult HandleListenRequest(const IOCtlRequest& request);
IPCCommandResult HandleGetSockOptRequest(const IOCtlRequest& request);
IPCCommandResult HandleSetSockOptRequest(const IOCtlRequest& request);
IPCCommandResult HandleGetSockNameRequest(const IOCtlRequest& request);
IPCCommandResult HandleGetPeerNameRequest(const IOCtlRequest& request);
IPCCommandResult HandleGetHostIDRequest(const IOCtlRequest& request);
IPCCommandResult HandleInetAToNRequest(const IOCtlRequest& request);
IPCCommandResult HandleInetPToNRequest(const IOCtlRequest& request);
IPCCommandResult HandleInetNToPRequest(const IOCtlRequest& request);
IPCCommandResult HandlePollRequest(const IOCtlRequest& request);
IPCCommandResult HandleGetHostByNameRequest(const IOCtlRequest& request);
IPCCommandResult HandleICMPCancelRequest(const IOCtlRequest& request);
IPCReply HandleInitInterfaceRequest(const IOCtlRequest& request);
IPCReply HandleSocketRequest(const IOCtlRequest& request);
IPCReply HandleICMPSocketRequest(const IOCtlRequest& request);
IPCReply HandleCloseRequest(const IOCtlRequest& request);
std::optional<IPCReply> HandleDoSockRequest(const IOCtlRequest& request);
IPCReply HandleShutdownRequest(const IOCtlRequest& request);
IPCReply HandleListenRequest(const IOCtlRequest& request);
IPCReply HandleGetSockOptRequest(const IOCtlRequest& request);
IPCReply HandleSetSockOptRequest(const IOCtlRequest& request);
IPCReply HandleGetSockNameRequest(const IOCtlRequest& request);
IPCReply HandleGetPeerNameRequest(const IOCtlRequest& request);
IPCReply HandleGetHostIDRequest(const IOCtlRequest& request);
IPCReply HandleInetAToNRequest(const IOCtlRequest& request);
IPCReply HandleInetPToNRequest(const IOCtlRequest& request);
IPCReply HandleInetNToPRequest(const IOCtlRequest& request);
std::optional<IPCReply> HandlePollRequest(const IOCtlRequest& request);
IPCReply HandleGetHostByNameRequest(const IOCtlRequest& request);
IPCReply HandleICMPCancelRequest(const IOCtlRequest& request);
IPCCommandResult HandleGetInterfaceOptRequest(const IOCtlVRequest& request);
IPCCommandResult HandleSendToRequest(const IOCtlVRequest& request);
IPCCommandResult HandleRecvFromRequest(const IOCtlVRequest& request);
IPCCommandResult HandleGetAddressInfoRequest(const IOCtlVRequest& request);
IPCCommandResult HandleICMPPingRequest(const IOCtlVRequest& request);
IPCReply HandleGetInterfaceOptRequest(const IOCtlVRequest& request);
std::optional<IPCReply> HandleSendToRequest(const IOCtlVRequest& request);
std::optional<IPCReply> HandleRecvFromRequest(const IOCtlVRequest& request);
IPCReply HandleGetAddressInfoRequest(const IOCtlVRequest& request);
IPCReply HandleICMPPingRequest(const IOCtlVRequest& request);
#ifdef _WIN32
WSADATA InitData;

View File

@ -32,7 +32,7 @@ NetKDRequestDevice::~NetKDRequestDevice()
WiiSockMan::GetInstance().Clean();
}
IPCCommandResult NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
{
s32 return_value = 0;
switch (request.request)
@ -169,7 +169,7 @@ IPCCommandResult NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
request.Log(GetDeviceName(), Common::Log::IOS_WC24);
}
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
u8 NetKDRequestDevice::GetAreaCode(const std::string& area) const

View File

@ -21,7 +21,7 @@ public:
NetKDRequestDevice(Kernel& ios, const std::string& device_name);
~NetKDRequestDevice() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
private:
enum

View File

@ -19,7 +19,7 @@ NetKDTimeDevice::NetKDTimeDevice(Kernel& ios, const std::string& device_name)
NetKDTimeDevice::~NetKDTimeDevice() = default;
IPCCommandResult NetKDTimeDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> NetKDTimeDevice::IOCtl(const IOCtlRequest& request)
{
s32 result = 0;
u32 common_result = 0;
@ -72,7 +72,7 @@ IPCCommandResult NetKDTimeDevice::IOCtl(const IOCtlRequest& request)
// write return values
Memory::Write_U32(common_result, request.buffer_out);
return GetDefaultReply(result);
return IPCReply(result);
}
u64 NetKDTimeDevice::GetAdjustedUTC() const

View File

@ -17,7 +17,7 @@ public:
NetKDTimeDevice(Kernel& ios, const std::string& device_name);
~NetKDTimeDevice() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
private:
// TODO: depending on CEXIIPL is a hack which I don't feel like

View File

@ -27,7 +27,7 @@ void NetNCDManageDevice::DoState(PointerWrap& p)
p.Do(m_ipc_fd);
}
IPCCommandResult NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
{
s32 return_value = IPC_SUCCESS;
u32 common_result = 0;
@ -37,10 +37,10 @@ IPCCommandResult NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
{
case IOCTLV_NCD_LOCKWIRELESSDRIVER:
if (!request.HasNumberOfValidVectors(0, 1))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
if (request.io_vectors[0].size < 2 * sizeof(u32))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
if (m_ipc_fd != 0)
{
@ -60,13 +60,13 @@ IPCCommandResult NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
case IOCTLV_NCD_UNLOCKWIRELESSDRIVER:
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
if (request.in_vectors[0].size < sizeof(u32))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
if (request.io_vectors[0].size < sizeof(u32))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
const u32 request_handle = Memory::Read_U32(request.in_vectors[0].address);
if (m_ipc_fd == request_handle)
@ -130,6 +130,6 @@ IPCCommandResult NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
{
Memory::Write_U32(common_result, request.io_vectors.at(common_vector).address + 4);
}
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
} // namespace IOS::HLE

View File

@ -18,7 +18,7 @@ class NetNCDManageDevice : public Device
public:
NetNCDManageDevice(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
void DoState(PointerWrap& p) override;

View File

@ -113,10 +113,10 @@ int NetSSLDevice::GetSSLFreeID() const
return 0;
}
IPCCommandResult NetSSLDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> NetSSLDevice::IOCtl(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), Common::Log::IOS_SSL, Common::Log::LINFO);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
constexpr std::array<u8, 32> s_client_cert_hash = {
@ -167,7 +167,7 @@ static std::vector<u8> ReadCertFile(const std::string& path, const std::array<u8
return bytes;
}
IPCCommandResult NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
{
u32 BufferIn = 0, BufferIn2 = 0, BufferIn3 = 0;
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
@ -210,7 +210,7 @@ IPCCommandResult NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
// I don't trust SSL to be deterministic, and this is never going to sync
// as such (as opposed to forwarding IPC results or whatever), so -
if (Core::WantsDeterminism())
return GetDefaultReply(IPC_EACCES);
return IPCReply(IPC_EACCES);
switch (request.request)
{
@ -499,7 +499,7 @@ IPCCommandResult NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
{
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_DOHANDSHAKE);
return GetNoReply();
return std::nullopt;
}
else
{
@ -514,7 +514,7 @@ IPCCommandResult NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
{
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_WRITE);
return GetNoReply();
return std::nullopt;
}
else
{
@ -538,7 +538,7 @@ IPCCommandResult NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
{
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_READ);
return GetNoReply();
return std::nullopt;
}
else
{
@ -600,6 +600,6 @@ IPCCommandResult NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
// SSL return codes are written to BufferIn
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE

View File

@ -87,8 +87,8 @@ public:
virtual ~NetSSLDevice();
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
int GetSSLFreeID() const;

View File

@ -183,7 +183,7 @@ void NetWDCommandDevice::DoState(PointerWrap& p)
p.Do(m_recv_notification_requests);
}
IPCCommandResult NetWDCommandDevice::Open(const OpenRequest& request)
std::optional<IPCReply> NetWDCommandDevice::Open(const OpenRequest& request)
{
if (m_ipc_owner_fd < 0)
{
@ -197,7 +197,7 @@ IPCCommandResult NetWDCommandDevice::Open(const OpenRequest& request)
{
ERROR_LOG_FMT(IOS_NET, "Unsupported WD operating mode: {}", mode);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNCOMMON_WD_MODE);
return GetDefaultReply(s32(ResultCode::UnavailableCommand));
return IPCReply(s32(ResultCode::UnavailableCommand));
}
if (m_target_status == Status::Idle && mode <= WD::Mode::Unknown6)
@ -212,12 +212,12 @@ IPCCommandResult NetWDCommandDevice::Open(const OpenRequest& request)
return Device::Open(request);
}
IPCCommandResult NetWDCommandDevice::Close(u32 fd)
std::optional<IPCReply> NetWDCommandDevice::Close(u32 fd)
{
if (m_ipc_owner_fd < 0 || fd != u32(m_ipc_owner_fd))
{
ERROR_LOG_FMT(IOS_NET, "Invalid close attempt.");
return GetDefaultReply(u32(ResultCode::InvalidFd));
return IPCReply(u32(ResultCode::InvalidFd));
}
INFO_LOG_FMT(IOS_NET, "Closing and resetting status to Idle");
@ -228,11 +228,11 @@ IPCCommandResult NetWDCommandDevice::Close(u32 fd)
return Device::Close(fd);
}
IPCCommandResult NetWDCommandDevice::SetLinkState(const IOCtlVRequest& request)
IPCReply NetWDCommandDevice::SetLinkState(const IOCtlVRequest& request)
{
const auto* vector = request.GetVector(0);
if (!vector || vector->address == 0)
return GetDefaultReply(u32(ResultCode::IllegalParameter));
return IPCReply(u32(ResultCode::IllegalParameter));
const u32 state = Memory::Read_U32(vector->address);
INFO_LOG_FMT(IOS_NET, "WD_SetLinkState called (state={}, mode={})", state, m_mode);
@ -240,7 +240,7 @@ IPCCommandResult NetWDCommandDevice::SetLinkState(const IOCtlVRequest& request)
if (state == 0)
{
if (!WD::IsValidMode(m_mode))
return GetDefaultReply(u32(ResultCode::UnavailableCommand));
return IPCReply(u32(ResultCode::UnavailableCommand));
INFO_LOG_FMT(IOS_NET, "WD_SetLinkState: setting target status to 1 (Idle)");
m_target_status = Status::Idle;
@ -248,37 +248,37 @@ IPCCommandResult NetWDCommandDevice::SetLinkState(const IOCtlVRequest& request)
else
{
if (state != 1)
return GetDefaultReply(u32(ResultCode::IllegalParameter));
return IPCReply(u32(ResultCode::IllegalParameter));
if (!WD::IsValidMode(m_mode))
return GetDefaultReply(u32(ResultCode::UnavailableCommand));
return IPCReply(u32(ResultCode::UnavailableCommand));
const auto target_status = GetTargetStatusForMode(m_mode);
if (m_status != target_status && m_info.enabled_channels == 0)
return GetDefaultReply(u32(ResultCode::UnavailableCommand));
return IPCReply(u32(ResultCode::UnavailableCommand));
INFO_LOG_FMT(IOS_NET, "WD_SetLinkState: setting target status to {}", target_status);
m_target_status = target_status;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult NetWDCommandDevice::GetLinkState(const IOCtlVRequest& request) const
IPCReply NetWDCommandDevice::GetLinkState(const IOCtlVRequest& request) const
{
INFO_LOG_FMT(IOS_NET, "WD_GetLinkState called (status={}, mode={})", m_status, m_mode);
if (!WD::IsValidMode(m_mode))
return GetDefaultReply(u32(ResultCode::UnavailableCommand));
return IPCReply(u32(ResultCode::UnavailableCommand));
// Contrary to what the name of the ioctl suggests, this returns a boolean, not the current state.
return GetDefaultReply(u32(m_status == GetTargetStatusForMode(m_mode)));
return IPCReply(u32(m_status == GetTargetStatusForMode(m_mode)));
}
IPCCommandResult NetWDCommandDevice::Disassociate(const IOCtlVRequest& request)
IPCReply NetWDCommandDevice::Disassociate(const IOCtlVRequest& request)
{
const auto* vector = request.GetVector(0);
if (!vector || vector->address == 0)
return GetDefaultReply(u32(ResultCode::IllegalParameter));
return IPCReply(u32(ResultCode::IllegalParameter));
Common::MACAddress mac;
Memory::CopyFromEmu(mac.data(), vector->address, mac.size());
@ -289,7 +289,7 @@ IPCCommandResult NetWDCommandDevice::Disassociate(const IOCtlVRequest& request)
m_mode != WD::Mode::Unknown6)
{
ERROR_LOG_FMT(IOS_NET, "WD_Disassociate: cannot disassociate in mode {}", m_mode);
return GetDefaultReply(u32(ResultCode::UnavailableCommand));
return IPCReply(u32(ResultCode::UnavailableCommand));
}
const auto target_status = GetTargetStatusForMode(m_mode);
@ -297,31 +297,31 @@ IPCCommandResult NetWDCommandDevice::Disassociate(const IOCtlVRequest& request)
{
ERROR_LOG_FMT(IOS_NET, "WD_Disassociate: cannot disassociate in status {} (target {})",
m_status, target_status);
return GetDefaultReply(u32(ResultCode::UnavailableCommand));
return IPCReply(u32(ResultCode::UnavailableCommand));
}
// TODO: Check the input MAC address and only return 0x80008001 if it is unknown.
return GetDefaultReply(u32(ResultCode::IllegalParameter));
return IPCReply(u32(ResultCode::IllegalParameter));
}
IPCCommandResult NetWDCommandDevice::GetInfo(const IOCtlVRequest& request) const
IPCReply NetWDCommandDevice::GetInfo(const IOCtlVRequest& request) const
{
const auto* vector = request.GetVector(0);
if (!vector || vector->address == 0)
return GetDefaultReply(u32(ResultCode::IllegalParameter));
return IPCReply(u32(ResultCode::IllegalParameter));
Memory::CopyToEmu(vector->address, &m_info, sizeof(m_info));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request)
{
switch (request.request)
{
case IOCTLV_WD_INVALID:
return GetDefaultReply(u32(ResultCode::UnavailableCommand));
return IPCReply(u32(ResultCode::UnavailableCommand));
case IOCTLV_WD_GET_MODE:
return GetDefaultReply(s32(m_mode));
return IPCReply(s32(m_mode));
case IOCTLV_WD_SET_LINKSTATE:
return SetLinkState(request);
case IOCTLV_WD_GET_LINKSTATE:
@ -361,11 +361,11 @@ IPCCommandResult NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request)
case IOCTLV_WD_RECV_FRAME:
m_recv_frame_requests.emplace_back(request.address);
return GetNoReply();
return std::nullopt;
case IOCTLV_WD_RECV_NOTIFICATION:
m_recv_notification_requests.emplace_back(request.address);
return GetNoReply();
return std::nullopt;
case IOCTLV_WD_SET_CONFIG:
case IOCTLV_WD_GET_CONFIG:
@ -382,6 +382,6 @@ IPCCommandResult NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request)
request.Dump(GetDeviceName(), Common::Log::IOS_NET, Common::Log::LWARNING);
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE

View File

@ -52,9 +52,9 @@ public:
NetWDCommandDevice(Kernel& ios, const std::string& device_name);
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
void Update() override;
bool IsOpened() const override { return true; }
void DoState(PointerWrap& p) override;
@ -153,10 +153,10 @@ private:
void HandleStateChange();
static Status GetTargetStatusForMode(WD::Mode mode);
IPCCommandResult SetLinkState(const IOCtlVRequest& request);
IPCCommandResult GetLinkState(const IOCtlVRequest& request) const;
IPCCommandResult Disassociate(const IOCtlVRequest& request);
IPCCommandResult GetInfo(const IOCtlVRequest& request) const;
IPCReply SetLinkState(const IOCtlVRequest& request);
IPCReply GetLinkState(const IOCtlVRequest& request) const;
IPCReply Disassociate(const IOCtlVRequest& request);
IPCReply GetInfo(const IOCtlVRequest& request) const;
s32 m_ipc_owner_fd = -1;
WD::Mode m_mode = WD::Mode::NotInitialized;

View File

@ -79,17 +79,17 @@ void SDIOSlot0Device::OpenInternal()
}
}
IPCCommandResult SDIOSlot0Device::Open(const OpenRequest& request)
std::optional<IPCReply> SDIOSlot0Device::Open(const OpenRequest& request)
{
OpenInternal();
m_registers.fill(0);
m_is_active = true;
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::Close(u32 fd)
std::optional<IPCReply> SDIOSlot0Device::Close(u32 fd)
{
m_card.Close();
m_block_length = 0;
@ -98,7 +98,7 @@ IPCCommandResult SDIOSlot0Device::Close(u32 fd)
return Device::Close(fd);
}
IPCCommandResult SDIOSlot0Device::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> SDIOSlot0Device::IOCtl(const IOCtlRequest& request)
{
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
@ -123,10 +123,10 @@ IPCCommandResult SDIOSlot0Device::IOCtl(const IOCtlRequest& request)
break;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> SDIOSlot0Device::IOCtlV(const IOCtlVRequest& request)
{
switch (request.request)
{
@ -137,7 +137,7 @@ IPCCommandResult SDIOSlot0Device::IOCtlV(const IOCtlVRequest& request)
break;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 buffer_in_size,
@ -325,7 +325,7 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
return ret;
}
IPCCommandResult SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)
IPCReply SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)
{
const u32 reg = Memory::Read_U32(request.buffer_in);
const u32 val = Memory::Read_U32(request.buffer_in + 16);
@ -335,7 +335,7 @@ IPCCommandResult SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)
if (reg >= m_registers.size())
{
WARN_LOG_FMT(IOS_SD, "IOCTL_WRITEHCR out of range");
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
if ((reg == HCR_CLOCKCONTROL) && (val & 1))
@ -354,17 +354,17 @@ IPCCommandResult SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)
m_registers[reg] = val;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::ReadHCRegister(const IOCtlRequest& request)
IPCReply SDIOSlot0Device::ReadHCRegister(const IOCtlRequest& request)
{
const u32 reg = Memory::Read_U32(request.buffer_in);
if (reg >= m_registers.size())
{
WARN_LOG_FMT(IOS_SD, "IOCTL_READHCR out of range");
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
const u32 val = m_registers[reg];
@ -372,20 +372,20 @@ IPCCommandResult SDIOSlot0Device::ReadHCRegister(const IOCtlRequest& request)
// Just reading the register
Memory::Write_U32(val, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::ResetCard(const IOCtlRequest& request)
IPCReply SDIOSlot0Device::ResetCard(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_RESETCARD");
// Returns 16bit RCA and 16bit 0s (meaning success)
Memory::Write_U32(m_status, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::SetClk(const IOCtlRequest& request)
IPCReply SDIOSlot0Device::SetClk(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_SETCLK");
@ -395,10 +395,10 @@ IPCCommandResult SDIOSlot0Device::SetClk(const IOCtlRequest& request)
if (clock != 1)
INFO_LOG_FMT(IOS_SD, "Setting to {}, interesting", clock);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::SendCommand(const IOCtlRequest& request)
std::optional<IPCReply> SDIOSlot0Device::SendCommand(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_SENDCMD {:x} IPC:{:08x}", Memory::Read_U32(request.buffer_in),
request.address);
@ -410,13 +410,13 @@ IPCCommandResult SDIOSlot0Device::SendCommand(const IOCtlRequest& request)
{
// Check if the condition is already true
EventNotify();
return GetNoReply();
return std::nullopt;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::GetStatus(const IOCtlRequest& request)
IPCReply SDIOSlot0Device::GetStatus(const IOCtlRequest& request)
{
// Since IOS does the SD initialization itself, we just say we're always initialized.
if (m_card)
@ -450,19 +450,19 @@ IPCCommandResult SDIOSlot0Device::GetStatus(const IOCtlRequest& request)
(status & CARD_INITIALIZED) ? " and initialized" : "");
Memory::Write_U32(status, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::GetOCRegister(const IOCtlRequest& request)
IPCReply SDIOSlot0Device::GetOCRegister(const IOCtlRequest& request)
{
const u32 ocr = GetOCRegister();
INFO_LOG_FMT(IOS_SD, "IOCTL_GETOCR. Replying with ocr {:x}", ocr);
Memory::Write_U32(ocr, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0Device::SendCommand(const IOCtlVRequest& request)
IPCReply SDIOSlot0Device::SendCommand(const IOCtlVRequest& request)
{
DEBUG_LOG_FMT(IOS_SD, "IOCTLV_SENDCMD {:#010x}", Memory::Read_U32(request.in_vectors[0].address));
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
@ -472,7 +472,7 @@ IPCCommandResult SDIOSlot0Device::SendCommand(const IOCtlVRequest& request)
request.in_vectors[1].address, request.in_vectors[1].size,
request.io_vectors[0].address, request.io_vectors[0].size);
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
u32 SDIOSlot0Device::GetOCRegister() const

View File

@ -26,10 +26,10 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
void EventNotify();
@ -125,15 +125,15 @@ private:
Request request;
};
IPCCommandResult WriteHCRegister(const IOCtlRequest& request);
IPCCommandResult ReadHCRegister(const IOCtlRequest& request);
IPCCommandResult ResetCard(const IOCtlRequest& request);
IPCCommandResult SetClk(const IOCtlRequest& request);
IPCCommandResult SendCommand(const IOCtlRequest& request);
IPCCommandResult GetStatus(const IOCtlRequest& request);
IPCCommandResult GetOCRegister(const IOCtlRequest& request);
IPCReply WriteHCRegister(const IOCtlRequest& request);
IPCReply ReadHCRegister(const IOCtlRequest& request);
IPCReply ResetCard(const IOCtlRequest& request);
IPCReply SetClk(const IOCtlRequest& request);
std::optional<IPCReply> SendCommand(const IOCtlRequest& request);
IPCReply GetStatus(const IOCtlRequest& request);
IPCReply GetOCRegister(const IOCtlRequest& request);
IPCCommandResult SendCommand(const IOCtlVRequest& request);
IPCReply SendCommand(const IOCtlVRequest& request);
s32 ExecuteCommand(const Request& request, u32 buffer_in, u32 buffer_in_size, u32 rw_buffer,
u32 rw_buffer_size, u32 buffer_out, u32 buffer_out_size);

View File

@ -16,7 +16,7 @@ namespace IOS::HLE
{
static std::unique_ptr<IOCtlRequest> s_event_hook_request;
IPCCommandResult STMImmediateDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
{
s32 return_value = IPC_SUCCESS;
switch (request.request)
@ -59,7 +59,7 @@ IPCCommandResult STMImmediateDevice::IOCtl(const IOCtlRequest& request)
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_STM);
}
return GetDefaultReply(return_value);
return IPCReply(return_value);
}
STMEventHookDevice::~STMEventHookDevice()
@ -67,17 +67,17 @@ STMEventHookDevice::~STMEventHookDevice()
s_event_hook_request.reset();
}
IPCCommandResult STMEventHookDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> STMEventHookDevice::IOCtl(const IOCtlRequest& request)
{
if (request.request != IOCTL_STM_EVENTHOOK)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
if (s_event_hook_request)
return GetDefaultReply(IPC_EEXIST);
return IPCReply(IPC_EEXIST);
// IOCTL_STM_EVENTHOOK waits until the reset button or power button is pressed.
s_event_hook_request = std::make_unique<IOCtlRequest>(request.address);
return GetNoReply();
return std::nullopt;
}
void STMEventHookDevice::DoState(PointerWrap& p)

View File

@ -43,7 +43,7 @@ class STMImmediateDevice final : public Device
{
public:
using Device::Device;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
};
// The /dev/stm/eventhook
@ -52,7 +52,7 @@ class STMEventHookDevice final : public Device
public:
using Device::Device;
~STMEventHookDevice() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
void DoState(PointerWrap& p) override;
bool HasHookInstalled() const;

View File

@ -127,7 +127,7 @@ bool BluetoothEmuDevice::RemoteDisconnect(const bdaddr_t& address)
return SendEventDisconnect(GetConnectionHandle(address), 0x13);
}
IPCCommandResult BluetoothEmuDevice::Close(u32 fd)
std::optional<IPCReply> BluetoothEmuDevice::Close(u32 fd)
{
// Clean up state
m_scan_enable = 0;
@ -139,7 +139,7 @@ IPCCommandResult BluetoothEmuDevice::Close(u32 fd)
return Device::Close(fd);
}
IPCCommandResult BluetoothEmuDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> BluetoothEmuDevice::IOCtlV(const IOCtlVRequest& request)
{
bool send_reply = true;
switch (request.request)
@ -204,7 +204,9 @@ IPCCommandResult BluetoothEmuDevice::IOCtlV(const IOCtlVRequest& request)
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_WIIMOTE);
}
return send_reply ? GetDefaultReply(IPC_SUCCESS) : GetNoReply();
if (!send_reply)
return std::nullopt;
return IPCReply(IPC_SUCCESS);
}
// Here we handle the USB::IOCTLV_USBV0_BLKMSG Ioctlv

View File

@ -44,8 +44,8 @@ public:
virtual ~BluetoothEmuDevice();
IPCCommandResult Close(u32 fd) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
void Update() override;

View File

@ -77,10 +77,10 @@ BluetoothRealDevice::~BluetoothRealDevice()
SaveLinkKeys();
}
IPCCommandResult BluetoothRealDevice::Open(const OpenRequest& request)
std::optional<IPCReply> BluetoothRealDevice::Open(const OpenRequest& request)
{
if (!m_context.IsValid())
return GetDefaultReply(IPC_EACCES);
return IPCReply(IPC_EACCES);
m_last_open_error.clear();
m_context.GetDeviceList([this](libusb_device* device) {
@ -132,13 +132,13 @@ IPCCommandResult BluetoothRealDevice::Open(const OpenRequest& request)
m_last_open_error);
}
Core::QueueHostJob(Core::Stop);
return GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
}
return Device::Open(request);
}
IPCCommandResult BluetoothRealDevice::Close(u32 fd)
std::optional<IPCReply> BluetoothRealDevice::Close(u32 fd)
{
if (m_handle)
{
@ -151,7 +151,7 @@ IPCCommandResult BluetoothRealDevice::Close(u32 fd)
return Device::Close(fd);
}
IPCCommandResult BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request)
{
if (!m_is_wii_bt_module && m_need_reset_keys.TestAndClear())
{
@ -173,13 +173,13 @@ IPCCommandResult BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request)
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
m_fake_read_buffer_size_reply.Set();
return GetNoReply();
return std::nullopt;
}
if (!m_is_wii_bt_module && (opcode == 0xFC4C || opcode == 0xFC4F))
{
m_fake_vendor_command_reply.Set();
m_fake_vendor_command_reply_opcode = opcode;
return GetNoReply();
return std::nullopt;
}
if (opcode == HCI_CMD_DELETE_STORED_LINK_KEY)
{
@ -218,23 +218,23 @@ IPCCommandResult BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request)
{
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
FakeSyncButtonPressedEvent(*cmd);
return GetNoReply();
return std::nullopt;
}
if (m_sync_button_state == SyncButtonState::LongPressed)
{
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
FakeSyncButtonHeldEvent(*cmd);
return GetNoReply();
return std::nullopt;
}
if (m_fake_read_buffer_size_reply.TestAndClear())
{
FakeReadBufferSizeReply(*cmd);
return GetNoReply();
return std::nullopt;
}
if (m_fake_vendor_command_reply.TestAndClear())
{
FakeVendorCommandReply(*cmd);
return GetNoReply();
return std::nullopt;
}
}
auto buffer = cmd->MakeBuffer(cmd->length);
@ -258,7 +258,7 @@ IPCCommandResult BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request)
}
}
// Replies are generated inside of the message handlers (and asynchronously).
return GetNoReply();
return std::nullopt;
}
static bool s_has_shown_savestate_warning = false;

View File

@ -46,9 +46,9 @@ public:
BluetoothRealDevice(Kernel& ios, const std::string& device_name);
~BluetoothRealDevice() override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
void DoState(PointerWrap& p) override;
void UpdateSyncButtonState(bool is_held) override;

View File

@ -10,11 +10,11 @@
namespace IOS::HLE
{
IPCCommandResult BluetoothStubDevice::Open(const OpenRequest& request)
std::optional<IPCReply> BluetoothStubDevice::Open(const OpenRequest& request)
{
PanicAlertFmtT("Bluetooth passthrough mode is enabled, but Dolphin was built without libusb."
" Passthrough mode cannot be used.");
return GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
}
void BluetoothStubDevice::DoState(PointerWrap& p)

View File

@ -18,7 +18,7 @@ class BluetoothStubDevice final : public BluetoothBaseDevice
{
public:
using BluetoothBaseDevice::BluetoothBaseDevice;
IPCCommandResult Open(const OpenRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
void DoState(PointerWrap& p) override;
};
} // namespace IOS::HLE

View File

@ -33,7 +33,7 @@ USBHost::USBHost(Kernel& ios, const std::string& device_name) : Device(ios, devi
USBHost::~USBHost() = default;
IPCCommandResult USBHost::Open(const OpenRequest& request)
std::optional<IPCReply> USBHost::Open(const OpenRequest& request)
{
if (!m_has_initialised && !Core::WantsDeterminism())
{
@ -43,7 +43,7 @@ IPCCommandResult USBHost::Open(const OpenRequest& request)
GetScanThread().WaitForFirstScan();
m_has_initialised = true;
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
void USBHost::UpdateWantDeterminism(const bool new_want_determinism)
@ -213,18 +213,18 @@ void USBHost::ScanThread::Stop()
m_host->DispatchHooks(hooks);
}
IPCCommandResult USBHost::HandleTransfer(std::shared_ptr<USB::Device> device, u32 request,
std::function<s32()> submit) const
std::optional<IPCReply> USBHost::HandleTransfer(std::shared_ptr<USB::Device> device, u32 request,
std::function<s32()> submit) const
{
if (!device)
return GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
const s32 ret = submit();
if (ret == IPC_SUCCESS)
return GetNoReply();
return std::nullopt;
ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to submit transfer (request {}): {}",
device->GetVid(), device->GetPid(), request, device->GetErrorName(ret));
return GetDefaultReply(ret <= 0 ? ret : IPC_EINVAL);
return IPCReply(ret <= 0 ? ret : IPC_EINVAL);
}
} // namespace IOS::HLE

View File

@ -33,7 +33,7 @@ public:
USBHost(Kernel& ios, const std::string& device_name);
virtual ~USBHost();
IPCCommandResult Open(const OpenRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
void UpdateWantDeterminism(bool new_want_determinism) override;
void DoState(PointerWrap& p) override;
@ -72,8 +72,8 @@ protected:
virtual bool ShouldAddDevice(const USB::Device& device) const;
virtual ScanThread& GetScanThread() = 0;
IPCCommandResult HandleTransfer(std::shared_ptr<USB::Device> device, u32 request,
std::function<s32()> submit) const;
std::optional<IPCReply> HandleTransfer(std::shared_ptr<USB::Device> device, u32 request,
std::function<s32()> submit) const;
private:
bool AddDevice(std::unique_ptr<USB::Device> device);

View File

@ -31,14 +31,14 @@ OH0::~OH0()
m_scan_thread.Stop();
}
IPCCommandResult OH0::Open(const OpenRequest& request)
std::optional<IPCReply> OH0::Open(const OpenRequest& request)
{
if (HasFeature(m_ios.GetVersion(), Feature::NewUSB))
return GetDefaultReply(IPC_EACCES);
return IPCReply(IPC_EACCES);
return USBHost::Open(request);
}
IPCCommandResult OH0::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> OH0::IOCtl(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), Common::Log::IOS_USB);
switch (request.request)
@ -48,11 +48,11 @@ IPCCommandResult OH0::IOCtl(const IOCtlRequest& request)
case USB::IOCTL_USBV0_CANCEL_INSERT_HOOK:
return CancelInsertionHook(request);
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
IPCCommandResult OH0::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> OH0::IOCtlV(const IOCtlVRequest& request)
{
INFO_LOG_FMT(IOS_USB, "/dev/usb/oh0 - IOCtlV {}", request.request);
switch (request.request)
@ -70,7 +70,7 @@ IPCCommandResult OH0::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_DEVINSERTHOOKID:
return RegisterInsertionHookWithID(request);
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
@ -88,26 +88,26 @@ void OH0::DoState(PointerWrap& p)
USBHost::DoState(p);
}
IPCCommandResult OH0::CancelInsertionHook(const IOCtlRequest& request)
IPCReply OH0::CancelInsertionHook(const IOCtlRequest& request)
{
if (!request.buffer_in || request.buffer_in_size != 4)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
// IOS assigns random IDs, but ours are simply the VID + PID (see RegisterInsertionHookWithID)
TriggerHook(m_insertion_hooks,
{Memory::Read_U16(request.buffer_in), Memory::Read_U16(request.buffer_in + 2)},
USB_ECANCELED);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult OH0::GetDeviceList(const IOCtlVRequest& request) const
IPCReply OH0::GetDeviceList(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(2, 2))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
const u8 max_entries_count = Memory::Read_U8(request.in_vectors[0].address);
if (request.io_vectors[1].size != max_entries_count * sizeof(DeviceEntry))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
const u8 interface_class = Memory::Read_U8(request.in_vectors[1].address);
u8 entries_count = 0;
@ -126,91 +126,91 @@ IPCCommandResult OH0::GetDeviceList(const IOCtlVRequest& request) const
Memory::CopyToEmu(request.io_vectors[1].address + 8 * entries_count++, &entry, 8);
}
Memory::Write_U8(entries_count, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult OH0::GetRhDesca(const IOCtlRequest& request) const
IPCReply OH0::GetRhDesca(const IOCtlRequest& request) const
{
if (!request.buffer_out || request.buffer_out_size != 4)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
// Based on a hardware test, this ioctl seems to return a constant value
Memory::Write_U32(0x02000302, request.buffer_out);
request.Dump(GetDeviceName(), Common::Log::IOS_USB, Common::Log::LWARNING);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult OH0::GetRhPortStatus(const IOCtlVRequest& request) const
IPCReply OH0::GetRhPortStatus(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(1, 1))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
ERROR_LOG_FMT(IOS_USB, "Unimplemented IOCtlV: IOCTLV_USBV0_GETRHPORTSTATUS");
request.Dump(GetDeviceName(), Common::Log::IOS_USB, Common::Log::LERROR);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult OH0::SetRhPortStatus(const IOCtlVRequest& request)
IPCReply OH0::SetRhPortStatus(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
ERROR_LOG_FMT(IOS_USB, "Unimplemented IOCtlV: IOCTLV_USBV0_SETRHPORTSTATUS");
request.Dump(GetDeviceName(), Common::Log::IOS_USB, Common::Log::LERROR);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult OH0::RegisterRemovalHook(const u64 device_id, const IOCtlRequest& request)
std::optional<IPCReply> OH0::RegisterRemovalHook(const u64 device_id, const IOCtlRequest& request)
{
std::lock_guard lock{m_hooks_mutex};
// IOS only allows a single device removal hook.
if (m_removal_hooks.find(device_id) != m_removal_hooks.end())
return GetDefaultReply(IPC_EEXIST);
return IPCReply(IPC_EEXIST);
m_removal_hooks.insert({device_id, request.address});
return GetNoReply();
return std::nullopt;
}
IPCCommandResult OH0::RegisterInsertionHook(const IOCtlVRequest& request)
std::optional<IPCReply> OH0::RegisterInsertionHook(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(2, 0))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
const u16 vid = Memory::Read_U16(request.in_vectors[0].address);
const u16 pid = Memory::Read_U16(request.in_vectors[1].address);
if (HasDeviceWithVidPid(vid, pid))
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
std::lock_guard lock{m_hooks_mutex};
// TODO: figure out whether IOS allows more than one hook.
m_insertion_hooks[{vid, pid}] = request.address;
return GetNoReply();
return std::nullopt;
}
IPCCommandResult OH0::RegisterInsertionHookWithID(const IOCtlVRequest& request)
std::optional<IPCReply> OH0::RegisterInsertionHookWithID(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(3, 1))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
std::lock_guard lock{m_hooks_mutex};
const u16 vid = Memory::Read_U16(request.in_vectors[0].address);
const u16 pid = Memory::Read_U16(request.in_vectors[1].address);
const bool trigger_only_for_new_device = Memory::Read_U8(request.in_vectors[2].address) == 1;
if (!trigger_only_for_new_device && HasDeviceWithVidPid(vid, pid))
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
// TODO: figure out whether IOS allows more than one hook.
m_insertion_hooks.insert({{vid, pid}, request.address});
// The output vector is overwritten with an ID to use with ioctl 31 for cancelling the hook.
Memory::Write_U32(vid << 16 | pid, request.io_vectors[0].address);
return GetNoReply();
return std::nullopt;
}
IPCCommandResult OH0::RegisterClassChangeHook(const IOCtlVRequest& request)
std::optional<IPCReply> OH0::RegisterClassChangeHook(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
WARN_LOG_FMT(IOS_USB, "Unimplemented IOCtlV: USB::IOCTLV_USBV0_DEVICECLASSCHANGE (no reply)");
request.Dump(GetDeviceName(), Common::Log::IOS_USB, Common::Log::LWARNING);
return GetNoReply();
return std::nullopt;
}
bool OH0::HasDeviceWithVidPid(const u16 vid, const u16 pid) const
@ -270,11 +270,11 @@ void OH0::DeviceClose(const u64 device_id)
m_opened_devices.erase(device_id);
}
IPCCommandResult OH0::DeviceIOCtl(const u64 device_id, const IOCtlRequest& request)
std::optional<IPCReply> OH0::DeviceIOCtl(const u64 device_id, const IOCtlRequest& request)
{
const auto device = GetDeviceById(device_id);
if (!device)
return GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
switch (request.request)
{
@ -283,20 +283,20 @@ IPCCommandResult OH0::DeviceIOCtl(const u64 device_id, const IOCtlRequest& reque
case USB::IOCTL_USBV0_SUSPENDDEV:
case USB::IOCTL_USBV0_RESUMEDEV:
// Unimplemented because libusb doesn't do power management.
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV0_RESET_DEVICE:
TriggerHook(m_removal_hooks, device_id, IPC_SUCCESS);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
IPCCommandResult OH0::DeviceIOCtlV(const u64 device_id, const IOCtlVRequest& request)
std::optional<IPCReply> OH0::DeviceIOCtlV(const u64 device_id, const IOCtlVRequest& request)
{
const auto device = GetDeviceById(device_id);
if (!device)
return GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
switch (request.request)
{
@ -309,9 +309,9 @@ IPCCommandResult OH0::DeviceIOCtlV(const u64 device_id, const IOCtlVRequest& req
[&, this]() { return SubmitTransfer(*device, request); });
case USB::IOCTLV_USBV0_UNKNOWN_32:
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_USB);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}

View File

@ -37,27 +37,27 @@ public:
OH0(Kernel& ios, const std::string& device_name);
~OH0() override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
std::pair<ReturnCode, u64> DeviceOpen(u16 vid, u16 pid);
void DeviceClose(u64 device_id);
IPCCommandResult DeviceIOCtl(u64 device_id, const IOCtlRequest& request);
IPCCommandResult DeviceIOCtlV(u64 device_id, const IOCtlVRequest& request);
std::optional<IPCReply> DeviceIOCtl(u64 device_id, const IOCtlRequest& request);
std::optional<IPCReply> DeviceIOCtlV(u64 device_id, const IOCtlVRequest& request);
void DoState(PointerWrap& p) override;
private:
IPCCommandResult CancelInsertionHook(const IOCtlRequest& request);
IPCCommandResult GetDeviceList(const IOCtlVRequest& request) const;
IPCCommandResult GetRhDesca(const IOCtlRequest& request) const;
IPCCommandResult GetRhPortStatus(const IOCtlVRequest& request) const;
IPCCommandResult SetRhPortStatus(const IOCtlVRequest& request);
IPCCommandResult RegisterRemovalHook(u64 device_id, const IOCtlRequest& request);
IPCCommandResult RegisterInsertionHook(const IOCtlVRequest& request);
IPCCommandResult RegisterInsertionHookWithID(const IOCtlVRequest& request);
IPCCommandResult RegisterClassChangeHook(const IOCtlVRequest& request);
IPCReply CancelInsertionHook(const IOCtlRequest& request);
IPCReply GetDeviceList(const IOCtlVRequest& request) const;
IPCReply GetRhDesca(const IOCtlRequest& request) const;
IPCReply GetRhPortStatus(const IOCtlVRequest& request) const;
IPCReply SetRhPortStatus(const IOCtlVRequest& request);
std::optional<IPCReply> RegisterRemovalHook(u64 device_id, const IOCtlRequest& request);
std::optional<IPCReply> RegisterInsertionHook(const IOCtlVRequest& request);
std::optional<IPCReply> RegisterInsertionHookWithID(const IOCtlVRequest& request);
std::optional<IPCReply> RegisterClassChangeHook(const IOCtlVRequest& request);
s32 SubmitTransfer(USB::Device& device, const IOCtlVRequest& request);
bool HasDeviceWithVidPid(u16 vid, u16 pid) const;

View File

@ -51,30 +51,30 @@ void OH0Device::DoState(PointerWrap& p)
p.Do(m_device_id);
}
IPCCommandResult OH0Device::Open(const OpenRequest& request)
std::optional<IPCReply> OH0Device::Open(const OpenRequest& request)
{
if (m_vid == 0 && m_pid == 0)
return GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
m_oh0 = std::static_pointer_cast<OH0>(GetIOS()->GetDeviceByName("/dev/usb/oh0"));
ReturnCode return_code;
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);
return GetDefaultReply(return_code);
return IPCReply(return_code);
}
IPCCommandResult OH0Device::Close(u32 fd)
std::optional<IPCReply> OH0Device::Close(u32 fd)
{
m_oh0->DeviceClose(m_device_id);
return Device::Close(fd);
}
IPCCommandResult OH0Device::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> OH0Device::IOCtl(const IOCtlRequest& request)
{
return m_oh0->DeviceIOCtl(m_device_id, request);
}
IPCCommandResult OH0Device::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> OH0Device::IOCtlV(const IOCtlVRequest& request)
{
return m_oh0->DeviceIOCtlV(m_device_id, request);
}

View File

@ -20,10 +20,10 @@ class OH0Device final : public Device
public:
OH0Device(Kernel& ios, const std::string& device_name);
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Close(u32 fd) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
void DoState(PointerWrap& p) override;
private:

View File

@ -113,10 +113,10 @@ USBV5ResourceManager::USBV5Device* USBV5ResourceManager::GetUSBV5Device(u32 in_b
return usbv5_device;
}
IPCCommandResult USBV5ResourceManager::GetDeviceChange(const IOCtlRequest& request)
std::optional<IPCReply> USBV5ResourceManager::GetDeviceChange(const IOCtlRequest& request)
{
if (request.buffer_out_size != 0x180 || m_devicechange_hook_request)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
std::lock_guard lk{m_devicechange_hook_address_mutex};
m_devicechange_hook_request = std::make_unique<IOCtlRequest>(request.address);
@ -126,28 +126,27 @@ IPCCommandResult USBV5ResourceManager::GetDeviceChange(const IOCtlRequest& reque
TriggerDeviceChangeReply();
m_devicechange_first_call = false;
}
return GetNoReply();
return std::nullopt;
}
IPCCommandResult USBV5ResourceManager::SetAlternateSetting(USBV5Device& device,
const IOCtlRequest& request)
IPCReply USBV5ResourceManager::SetAlternateSetting(USBV5Device& device, const IOCtlRequest& request)
{
const auto host_device = GetDeviceById(device.host_id);
if (!host_device->AttachAndChangeInterface(device.interface_number))
return GetDefaultReply(-1);
return IPCReply(-1);
const u8 alt_setting = Memory::Read_U8(request.buffer_in + 2 * sizeof(s32));
const bool success = host_device->SetAltSetting(alt_setting) == 0;
return GetDefaultReply(success ? IPC_SUCCESS : IPC_EINVAL);
return IPCReply(success ? IPC_SUCCESS : IPC_EINVAL);
}
IPCCommandResult USBV5ResourceManager::Shutdown(const IOCtlRequest& request)
IPCReply USBV5ResourceManager::Shutdown(const IOCtlRequest& request)
{
if (request.buffer_in != 0 || request.buffer_in_size != 0 || request.buffer_out != 0 ||
request.buffer_out_size != 0)
{
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
std::lock_guard lk{m_devicechange_hook_address_mutex};
@ -156,11 +155,10 @@ IPCCommandResult USBV5ResourceManager::Shutdown(const IOCtlRequest& request)
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS);
m_devicechange_hook_request.reset();
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult USBV5ResourceManager::SuspendResume(USBV5Device& device,
const IOCtlRequest& request)
IPCReply USBV5ResourceManager::SuspendResume(USBV5Device& device, const IOCtlRequest& request)
{
const auto host_device = GetDeviceById(device.host_id);
const s32 resumed = Memory::Read_U32(request.buffer_in + 8);
@ -169,19 +167,19 @@ IPCCommandResult USBV5ResourceManager::SuspendResume(USBV5Device& device,
// platform-independant way (libusb does not support power management).
INFO_LOG_FMT(IOS_USB, "[{:04x}:{:04x} {}] Received {} command", host_device->GetVid(),
host_device->GetPid(), device.interface_number, resumed == 0 ? "suspend" : "resume");
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult USBV5ResourceManager::HandleDeviceIOCtl(const IOCtlRequest& request,
Handler handler)
std::optional<IPCReply> USBV5ResourceManager::HandleDeviceIOCtl(const IOCtlRequest& request,
Handler handler)
{
if (request.buffer_in == 0 || request.buffer_in_size != 0x20)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
std::lock_guard lock{m_usbv5_devices_mutex};
USBV5Device* device = GetUSBV5Device(request.buffer_in);
if (!device)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
return handler(*device);
}

View File

@ -68,8 +68,8 @@ class USBV5ResourceManager : public USBHost
public:
using USBHost::USBHost;
IPCCommandResult IOCtl(const IOCtlRequest& request) override = 0;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override = 0;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override = 0;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override = 0;
void DoState(PointerWrap& p) override;
@ -77,13 +77,13 @@ protected:
struct USBV5Device;
USBV5Device* GetUSBV5Device(u32 in_buffer);
IPCCommandResult GetDeviceChange(const IOCtlRequest& request);
IPCCommandResult SetAlternateSetting(USBV5Device& device, const IOCtlRequest& request);
IPCCommandResult Shutdown(const IOCtlRequest& request);
IPCCommandResult SuspendResume(USBV5Device& device, const IOCtlRequest& request);
std::optional<IPCReply> GetDeviceChange(const IOCtlRequest& request);
IPCReply SetAlternateSetting(USBV5Device& device, const IOCtlRequest& request);
IPCReply Shutdown(const IOCtlRequest& request);
IPCReply SuspendResume(USBV5Device& device, const IOCtlRequest& request);
using Handler = std::function<IPCCommandResult(USBV5Device&)>;
IPCCommandResult HandleDeviceIOCtl(const IOCtlRequest& request, Handler handler);
using Handler = std::function<std::optional<IPCReply>(USBV5Device&)>;
std::optional<IPCReply> HandleDeviceIOCtl(const IOCtlRequest& request, Handler handler);
void OnDeviceChange(ChangeEvent event, std::shared_ptr<USB::Device> device) override;
void OnDeviceChangeEnd() override;

View File

@ -31,20 +31,20 @@ USB_HIDv4::~USB_HIDv4()
m_scan_thread.Stop();
}
IPCCommandResult USB_HIDv4::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> USB_HIDv4::IOCtl(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), Common::Log::IOS_USB);
switch (request.request)
{
case USB::IOCTL_USBV4_GETVERSION:
return GetDefaultReply(VERSION);
return IPCReply(VERSION);
case USB::IOCTL_USBV4_GETDEVICECHANGE:
return GetDeviceChange(request);
case USB::IOCTL_USBV4_SHUTDOWN:
return Shutdown(request);
case USB::IOCTL_USBV4_SET_SUSPEND:
// Not implemented in IOS
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV4_CANCELINTERRUPT:
return CancelInterrupt(request);
case USB::IOCTL_USBV4_GET_US_STRING:
@ -53,36 +53,36 @@ IPCCommandResult USB_HIDv4::IOCtl(const IOCtlRequest& request)
case USB::IOCTL_USBV4_INTRMSG_OUT:
{
if (request.buffer_in == 0 || request.buffer_in_size != 32)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
const auto device = GetDeviceByIOSID(Memory::Read_U32(request.buffer_in + 16));
if (!device->Attach())
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
return HandleTransfer(device, request.request,
[&, this]() { return SubmitTransfer(*device, request); });
}
default:
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_USB);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
}
IPCCommandResult USB_HIDv4::CancelInterrupt(const IOCtlRequest& request)
IPCReply USB_HIDv4::CancelInterrupt(const IOCtlRequest& request)
{
if (request.buffer_in == 0 || request.buffer_in_size != 8)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
auto device = GetDeviceByIOSID(Memory::Read_U32(request.buffer_in));
if (!device)
return GetDefaultReply(IPC_ENOENT);
return IPCReply(IPC_ENOENT);
device->CancelTransfer(Memory::Read_U8(request.buffer_in + 4));
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult USB_HIDv4::GetDeviceChange(const IOCtlRequest& request)
std::optional<IPCReply> USB_HIDv4::GetDeviceChange(const IOCtlRequest& request)
{
std::lock_guard lk{m_devicechange_hook_address_mutex};
if (request.buffer_out == 0 || request.buffer_out_size != 0x600)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
m_devicechange_hook_request = std::make_unique<IOCtlRequest>(request.address);
// On the first call, the reply is sent immediately (instead of on device insertion/removal)
@ -91,10 +91,10 @@ IPCCommandResult USB_HIDv4::GetDeviceChange(const IOCtlRequest& request)
TriggerDeviceChangeReply();
m_devicechange_first_call = false;
}
return GetNoReply();
return std::nullopt;
}
IPCCommandResult USB_HIDv4::Shutdown(const IOCtlRequest& request)
IPCReply USB_HIDv4::Shutdown(const IOCtlRequest& request)
{
std::lock_guard lk{m_devicechange_hook_address_mutex};
if (m_devicechange_hook_request != 0)
@ -103,7 +103,7 @@ IPCCommandResult USB_HIDv4::Shutdown(const IOCtlRequest& request)
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, -1);
m_devicechange_hook_request.reset();
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
s32 USB_HIDv4::SubmitTransfer(USB::Device& device, const IOCtlRequest& request)

View File

@ -24,16 +24,16 @@ public:
USB_HIDv4(Kernel& ios, const std::string& device_name);
~USB_HIDv4() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
void DoState(PointerWrap& p) override;
private:
std::shared_ptr<USB::Device> GetDeviceByIOSID(s32 ios_id) const;
IPCCommandResult CancelInterrupt(const IOCtlRequest& request);
IPCCommandResult GetDeviceChange(const IOCtlRequest& request);
IPCCommandResult Shutdown(const IOCtlRequest& request);
IPCReply CancelInterrupt(const IOCtlRequest& request);
std::optional<IPCReply> GetDeviceChange(const IOCtlRequest& request);
IPCReply Shutdown(const IOCtlRequest& request);
s32 SubmitTransfer(USB::Device& device, const IOCtlRequest& request);
void TriggerDeviceChangeReply();

View File

@ -23,14 +23,14 @@ USB_HIDv5::~USB_HIDv5()
m_scan_thread.Stop();
}
IPCCommandResult USB_HIDv5::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> USB_HIDv5::IOCtl(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), Common::Log::IOS_USB);
switch (request.request)
{
case USB::IOCTL_USBV5_GETVERSION:
Memory::Write_U32(USBV5_VERSION, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV5_GETDEVICECHANGE:
return GetDeviceChange(request);
case USB::IOCTL_USBV5_SHUTDOWN:
@ -39,7 +39,7 @@ IPCCommandResult USB_HIDv5::IOCtl(const IOCtlRequest& request)
return HandleDeviceIOCtl(request,
[&](USBV5Device& device) { return GetDeviceInfo(device, request); });
case USB::IOCTL_USBV5_ATTACHFINISH:
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV5_SUSPEND_RESUME:
return HandleDeviceIOCtl(request,
[&](USBV5Device& device) { return SuspendResume(device, request); });
@ -48,11 +48,11 @@ IPCCommandResult USB_HIDv5::IOCtl(const IOCtlRequest& request)
[&](USBV5Device& device) { return CancelEndpoint(device, request); });
default:
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_USB, Common::Log::LERROR);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
}
IPCCommandResult USB_HIDv5::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> USB_HIDv5::IOCtlV(const IOCtlVRequest& request)
{
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_USB);
switch (request.request)
@ -63,12 +63,12 @@ IPCCommandResult USB_HIDv5::IOCtlV(const IOCtlVRequest& request)
{
// IOS does not check the number of vectors, but let's do that to avoid out-of-bounds reads.
if (request.in_vectors.size() + request.io_vectors.size() != 2)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
std::lock_guard lock{m_usbv5_devices_mutex};
USBV5Device* device = GetUSBV5Device(request.in_vectors[0].address);
if (!device)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
auto host_device = GetDeviceById(device->host_id);
if (request.request == USB::IOCTLV_USBV5_CTRLMSG)
host_device->Attach();
@ -78,7 +78,7 @@ IPCCommandResult USB_HIDv5::IOCtlV(const IOCtlVRequest& request)
[&, this]() { return SubmitTransfer(*device, *host_device, request); });
}
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
@ -109,7 +109,7 @@ s32 USB_HIDv5::SubmitTransfer(USBV5Device& device, USB::Device& host_device,
}
}
IPCCommandResult USB_HIDv5::CancelEndpoint(USBV5Device& device, const IOCtlRequest& request)
IPCReply USB_HIDv5::CancelEndpoint(USBV5Device& device, const IOCtlRequest& request)
{
const u8 value = Memory::Read_U8(request.buffer_in + 8);
u8 endpoint = 0;
@ -130,13 +130,13 @@ IPCCommandResult USB_HIDv5::CancelEndpoint(USBV5Device& device, const IOCtlReque
}
GetDeviceById(device.host_id)->CancelTransfer(endpoint);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult USB_HIDv5::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request)
IPCReply USB_HIDv5::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request)
{
if (request.buffer_out == 0 || request.buffer_out_size != 0x60)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
const std::shared_ptr<USB::Device> host_device = GetDeviceById(device.host_id);
const u8 alt_setting = Memory::Read_U8(request.buffer_in + 8);
@ -161,7 +161,7 @@ IPCCommandResult USB_HIDv5::GetDeviceInfo(USBV5Device& device, const IOCtlReques
interface.bAlternateSetting == alt_setting;
});
if (it == interfaces.end())
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
it->Swap();
Memory::CopyToEmu(request.buffer_out + 68, &*it, sizeof(*it));
@ -186,7 +186,7 @@ IPCCommandResult USB_HIDv5::GetDeviceInfo(USBV5Device& device, const IOCtlReques
}
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
bool USB_HIDv5::ShouldAddDevice(const USB::Device& device) const

View File

@ -17,12 +17,12 @@ public:
using USBV5ResourceManager::USBV5ResourceManager;
~USB_HIDv5() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
private:
IPCCommandResult CancelEndpoint(USBV5Device& device, const IOCtlRequest& request);
IPCCommandResult GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request);
IPCReply CancelEndpoint(USBV5Device& device, const IOCtlRequest& request);
IPCReply GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request);
s32 SubmitTransfer(USBV5Device& device, USB::Device& host_device, const IOCtlVRequest& ioctlv);
bool ShouldAddDevice(const USB::Device& device) const override;

View File

@ -188,7 +188,7 @@ USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, devi
{
}
IPCCommandResult USB_KBD::Open(const OpenRequest& request)
std::optional<IPCReply> USB_KBD::Open(const OpenRequest& request)
{
INFO_LOG_FMT(IOS, "USB_KBD: Open");
IniFile ini;
@ -203,13 +203,13 @@ IPCCommandResult USB_KBD::Open(const OpenRequest& request)
return Device::Open(request);
}
IPCCommandResult USB_KBD::Write(const ReadWriteRequest& request)
std::optional<IPCReply> USB_KBD::Write(const ReadWriteRequest& request)
{
// Stubbed.
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult USB_KBD::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> USB_KBD::IOCtl(const IOCtlRequest& request)
{
if (SConfig::GetInstance().m_WiiKeyboard && !Core::WantsDeterminism() &&
ControlReference::GetInputGate() && !m_message_queue.empty())
@ -217,7 +217,7 @@ IPCCommandResult USB_KBD::IOCtl(const IOCtlRequest& request)
Memory::CopyToEmu(request.buffer_out, &m_message_queue.front(), sizeof(MessageData));
m_message_queue.pop();
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
bool USB_KBD::IsKeyPressed(int key) const

View File

@ -20,9 +20,9 @@ class USB_KBD : public Device
public:
USB_KBD(Kernel& ios, const std::string& device_name);
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult Write(const ReadWriteRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> Open(const OpenRequest& request) override;
std::optional<IPCReply> Write(const ReadWriteRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
void Update() override;
private:

View File

@ -23,14 +23,14 @@ USB_VEN::~USB_VEN()
m_scan_thread.Stop();
}
IPCCommandResult USB_VEN::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> USB_VEN::IOCtl(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), Common::Log::IOS_USB);
switch (request.request)
{
case USB::IOCTL_USBV5_GETVERSION:
Memory::Write_U32(USBV5_VERSION, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV5_GETDEVICECHANGE:
return GetDeviceChange(request);
case USB::IOCTL_USBV5_SHUTDOWN:
@ -39,7 +39,7 @@ IPCCommandResult USB_VEN::IOCtl(const IOCtlRequest& request)
return HandleDeviceIOCtl(request,
[&](USBV5Device& device) { return GetDeviceInfo(device, request); });
case USB::IOCTL_USBV5_ATTACHFINISH:
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV5_SETALTERNATE:
return HandleDeviceIOCtl(
request, [&](USBV5Device& device) { return SetAlternateSetting(device, request); });
@ -51,11 +51,11 @@ IPCCommandResult USB_VEN::IOCtl(const IOCtlRequest& request)
[&](USBV5Device& device) { return CancelEndpoint(device, request); });
default:
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_USB, Common::Log::LERROR);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
}
IPCCommandResult USB_VEN::IOCtlV(const IOCtlVRequest& request)
std::optional<IPCReply> USB_VEN::IOCtlV(const IOCtlVRequest& request)
{
static const std::map<u32, u32> s_num_vectors = {
{USB::IOCTLV_USBV5_CTRLMSG, 2},
@ -72,12 +72,12 @@ IPCCommandResult USB_VEN::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV5_ISOMSG:
{
if (request.in_vectors.size() + request.io_vectors.size() != s_num_vectors.at(request.request))
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
std::lock_guard lock{m_usbv5_devices_mutex};
USBV5Device* device = GetUSBV5Device(request.in_vectors[0].address);
if (!device)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
auto host_device = GetDeviceById(device->host_id);
if (request.request == USB::IOCTLV_USBV5_CTRLMSG)
host_device->Attach();
@ -87,7 +87,7 @@ IPCCommandResult USB_VEN::IOCtlV(const IOCtlVRequest& request)
[&, this]() { return SubmitTransfer(*host_device, request); });
}
default:
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
}
}
@ -108,19 +108,19 @@ s32 USB_VEN::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
}
}
IPCCommandResult USB_VEN::CancelEndpoint(USBV5Device& device, const IOCtlRequest& request)
IPCReply USB_VEN::CancelEndpoint(USBV5Device& device, const IOCtlRequest& request)
{
const u8 endpoint = Memory::Read_U8(request.buffer_in + 8);
// IPC_EINVAL (-4) is returned when no transfer was cancelled.
if (GetDeviceById(device.host_id)->CancelTransfer(endpoint) < 0)
return GetDefaultReply(IPC_EINVAL);
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_EINVAL);
return IPCReply(IPC_SUCCESS);
}
IPCCommandResult USB_VEN::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request)
IPCReply USB_VEN::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request)
{
if (request.buffer_out == 0 || request.buffer_out_size != 0xc0)
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
const std::shared_ptr<USB::Device> host_device = GetDeviceById(device.host_id);
const u8 alt_setting = Memory::Read_U8(request.buffer_in + 8);
@ -145,7 +145,7 @@ IPCCommandResult USB_VEN::GetDeviceInfo(USBV5Device& device, const IOCtlRequest&
interface.bAlternateSetting == alt_setting;
});
if (it == interfaces.end())
return GetDefaultReply(IPC_EINVAL);
return IPCReply(IPC_EINVAL);
it->Swap();
Memory::CopyToEmu(request.buffer_out + 52, &*it, sizeof(*it));
@ -157,6 +157,6 @@ IPCCommandResult USB_VEN::GetDeviceInfo(USBV5Device& device, const IOCtlRequest&
sizeof(endpoints[i]));
}
return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE

View File

@ -17,12 +17,12 @@ public:
using USBV5ResourceManager::USBV5ResourceManager;
~USB_VEN() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;
private:
IPCCommandResult CancelEndpoint(USBV5Device& device, const IOCtlRequest& request);
IPCCommandResult GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request);
IPCReply CancelEndpoint(USBV5Device& device, const IOCtlRequest& request);
IPCReply GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request);
s32 SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv);
bool HasInterfaceNumberInIDs() const override { return false; }

View File

@ -124,7 +124,7 @@ void WFSIDevice::FinalizePatchInstall()
File::CopyDir(WFS::NativePath(patch_dir), WFS::NativePath(current_title_dir), true);
}
IPCCommandResult WFSIDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
{
s32 return_error_code = IPC_SUCCESS;
@ -546,7 +546,7 @@ IPCCommandResult WFSIDevice::IOCtl(const IOCtlRequest& request)
break;
}
return GetDefaultReply(return_error_code);
return IPCReply(return_error_code);
}
u32 WFSIDevice::GetTmd(u16 group_id, u32 title_id, u64 subtitle_id, u32 address, u32* size) const

View File

@ -37,7 +37,7 @@ class WFSIDevice : public Device
public:
WFSIDevice(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
private:
u32 GetTmd(u16 group_id, u32 title_id, u64 subtitle_id, u32 address, u32* size) const;

View File

@ -31,7 +31,7 @@ WFSSRVDevice::WFSSRVDevice(Kernel& ios, const std::string& device_name) : Device
m_device_name = "msc01";
}
IPCCommandResult WFSSRVDevice::IOCtl(const IOCtlRequest& request)
std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
{
int return_error_code = IPC_SUCCESS;
@ -90,7 +90,7 @@ IPCCommandResult WFSSRVDevice::IOCtl(const IOCtlRequest& request)
// Leave hanging, but we need to acknowledge the request at shutdown time.
m_hanging.push_back(request.address);
return GetNoReply();
return std::nullopt;
case IOCTL_WFS_FLUSH:
// Nothing to do.
@ -359,7 +359,7 @@ IPCCommandResult WFSSRVDevice::IOCtl(const IOCtlRequest& request)
break;
}
return GetDefaultReply(return_error_code);
return IPCReply(return_error_code);
}
s32 WFSSRVDevice::Rename(std::string source, std::string dest) const

View File

@ -34,7 +34,7 @@ class WFSSRVDevice : public Device
public:
WFSSRVDevice(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
s32 Rename(std::string source, std::string dest) const;
void SetHomeDir(const std::string& home_dir);