@@ -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,21 +361,21 @@ IPCCommandResult NetIPTopDevice::IOCtlV(const IOCtlVRequest& request)
break;
}

return GetDefaultReply(IPC_SUCCESS);
return IPCReply(IPC_SUCCESS);
}

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,18 +508,18 @@ 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);
const int nat_optname = MapWiiSockOptNameToNative(optname);

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
@@ -68,36 +68,36 @@ class NetIPTopDevice : public Device
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;
@@ -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
@@ -21,7 +21,7 @@ class NetKDRequestDevice : public Device
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
@@ -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
@@ -17,7 +17,7 @@ class NetKDTimeDevice : public Device
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
@@ -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
@@ -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;

@@ -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
@@ -87,8 +87,8 @@ class NetSSLDevice : public Device

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;

@@ -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,57 +228,57 @@ 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);

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;
}
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,39 +289,39 @@ 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);
if (m_status != target_status)
{
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
@@ -52,9 +52,9 @@ class NetWDCommandDevice : public Device

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 @@ class NetWDCommandDevice : public Device
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;
@@ -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,38 +354,38 @@ 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];
INFO_LOG_FMT(IOS_SD, "IOCTL_READHCR {:#010x} - {:#010x}", reg, val);

// 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
@@ -26,10 +26,10 @@ class SDIOSlot0Device : public Device

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 @@ class SDIOSlot0Device : public Device
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);
@@ -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,25 +59,25 @@ IPCCommandResult STMImmediateDevice::IOCtl(const IOCtlRequest& request)
request.DumpUnknown(GetDeviceName(), Common::Log::IOS_STM);
}

return GetDefaultReply(return_value);
return IPCReply(return_value);
}

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)
@@ -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;
@@ -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
@@ -44,8 +44,8 @@ class BluetoothEmuDevice final : public BluetoothBaseDevice

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;

@@ -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;
@@ -46,9 +46,9 @@ class BluetoothRealDevice final : public BluetoothBaseDevice
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;
@@ -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)
@@ -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
@@ -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
@@ -33,7 +33,7 @@ class USBHost : public Device
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 @@ class USBHost : public Device
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);
@@ -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);
}
}

@@ -37,27 +37,27 @@ class OH0 final : public USBHost
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;
@@ -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);
}
@@ -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:
@@ -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);
}

@@ -68,22 +68,22 @@ 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;

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;
@@ -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)
@@ -24,16 +24,16 @@ class USB_HIDv4 final : public USBHost
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();
@@ -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
@@ -17,12 +17,12 @@ class USB_HIDv5 final : public USBV5ResourceManager
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;
@@ -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,21 +203,21 @@ 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())
{
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
@@ -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:
@@ -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
@@ -17,12 +17,12 @@ class USB_VEN final : public USBV5ResourceManager
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; }
@@ -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
@@ -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;
@@ -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
@@ -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);