Merge pull request #4661 from leoetlino/ios-request
IOS HLE: Deduplicate the request parsing code
This commit is contained in:
commit
63011f1402
|
@ -180,7 +180,7 @@ void Reset(bool hard)
|
||||||
{
|
{
|
||||||
if (!device)
|
if (!device)
|
||||||
continue;
|
continue;
|
||||||
device->Close(0, true);
|
device->Close();
|
||||||
device.reset();
|
device.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,12 +348,10 @@ static std::shared_ptr<IWII_IPC_HLE_Device> GetUnusedESDevice()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the FD for the newly opened device (on success) or an error code.
|
// Returns the FD for the newly opened device (on success) or an error code.
|
||||||
static s32 OpenDevice(const u32 address)
|
static s32 OpenDevice(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
const std::string device_name = Memory::GetString(Memory::Read_U32(address + 0xC));
|
|
||||||
const u32 open_mode = Memory::Read_U32(address + 0x10);
|
|
||||||
const s32 new_fd = GetFreeDeviceID();
|
const s32 new_fd = GetFreeDeviceID();
|
||||||
INFO_LOG(WII_IPC_HLE, "Opening %s (mode %d, fd %d)", device_name.c_str(), open_mode, new_fd);
|
INFO_LOG(WII_IPC_HLE, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd);
|
||||||
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
|
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_HLE, "Couldn't get a free fd, too many open files");
|
ERROR_LOG(WII_IPC_HLE, "Couldn't get a free fd, too many open files");
|
||||||
|
@ -361,80 +359,73 @@ static s32 OpenDevice(const u32 address)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<IWII_IPC_HLE_Device> device;
|
std::shared_ptr<IWII_IPC_HLE_Device> device;
|
||||||
if (device_name.find("/dev/es") == 0)
|
if (request.path == "/dev/es")
|
||||||
{
|
{
|
||||||
device = GetUnusedESDevice();
|
device = GetUnusedESDevice();
|
||||||
if (!device)
|
if (!device)
|
||||||
return IPC_EESEXHAUSTED;
|
return IPC_EESEXHAUSTED;
|
||||||
}
|
}
|
||||||
else if (device_name.find("/dev/") == 0)
|
else if (request.path.find("/dev/") == 0)
|
||||||
{
|
{
|
||||||
device = GetDeviceByName(device_name);
|
device = GetDeviceByName(request.path);
|
||||||
}
|
}
|
||||||
else if (device_name.find('/') == 0)
|
else if (request.path.find('/') == 0)
|
||||||
{
|
{
|
||||||
device = std::make_shared<CWII_IPC_HLE_Device_FileIO>(new_fd, device_name);
|
device = std::make_shared<CWII_IPC_HLE_Device_FileIO>(new_fd, request.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device)
|
if (!device)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_HLE, "Unknown device: %s", device_name.c_str());
|
ERROR_LOG(WII_IPC_HLE, "Unknown device: %s", request.path.c_str());
|
||||||
return IPC_ENOENT;
|
return IPC_ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(new_fd, address + 4);
|
const IOSReturnCode code = device->Open(request);
|
||||||
device->Open(address, open_mode);
|
if (code < IPC_SUCCESS)
|
||||||
const s32 open_return_code = Memory::Read_U32(address + 4);
|
return code;
|
||||||
if (open_return_code < 0)
|
|
||||||
return open_return_code;
|
|
||||||
s_fdmap[new_fd] = device;
|
s_fdmap[new_fd] = device;
|
||||||
return new_fd;
|
return new_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IPCCommandResult HandleCommand(const u32 address)
|
static IPCCommandResult HandleCommand(const IOSRequest& request)
|
||||||
{
|
{
|
||||||
const auto command = static_cast<IPCCommandType>(Memory::Read_U32(address));
|
if (request.command == IPC_CMD_OPEN)
|
||||||
if (command == IPC_CMD_OPEN)
|
|
||||||
{
|
{
|
||||||
const s32 new_fd = OpenDevice(address);
|
IOSOpenRequest open_request{request.address};
|
||||||
Memory::Write_U32(new_fd, address + 4);
|
const s32 new_fd = OpenDevice(open_request);
|
||||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
return IWII_IPC_HLE_Device::GetDefaultReply(new_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
const s32 fd = Memory::Read_U32(address + 8);
|
const auto device = (request.fd < IPC_MAX_FDS) ? s_fdmap[request.fd] : nullptr;
|
||||||
const auto device = (fd >= 0 && fd < IPC_MAX_FDS) ? s_fdmap[fd] : nullptr;
|
|
||||||
if (!device)
|
if (!device)
|
||||||
{
|
return IWII_IPC_HLE_Device::GetDefaultReply(IPC_EINVAL);
|
||||||
Memory::Write_U32(IPC_EINVAL, address + 4);
|
|
||||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (command)
|
switch (request.command)
|
||||||
{
|
{
|
||||||
case IPC_CMD_CLOSE:
|
case IPC_CMD_CLOSE:
|
||||||
s_fdmap[fd].reset();
|
s_fdmap[request.fd].reset();
|
||||||
// A close on a valid device returns IPC_SUCCESS.
|
device->Close();
|
||||||
Memory::Write_U32(IPC_SUCCESS, address + 4);
|
return IWII_IPC_HLE_Device::GetDefaultReply(IPC_SUCCESS);
|
||||||
return device->Close(address);
|
|
||||||
case IPC_CMD_READ:
|
case IPC_CMD_READ:
|
||||||
return device->Read(address);
|
return device->Read(IOSReadWriteRequest{request.address});
|
||||||
case IPC_CMD_WRITE:
|
case IPC_CMD_WRITE:
|
||||||
return device->Write(address);
|
return device->Write(IOSReadWriteRequest{request.address});
|
||||||
case IPC_CMD_SEEK:
|
case IPC_CMD_SEEK:
|
||||||
return device->Seek(address);
|
return device->Seek(IOSSeekRequest{request.address});
|
||||||
case IPC_CMD_IOCTL:
|
case IPC_CMD_IOCTL:
|
||||||
return device->IOCtl(address);
|
return device->IOCtl(IOSIOCtlRequest{request.address});
|
||||||
case IPC_CMD_IOCTLV:
|
case IPC_CMD_IOCTLV:
|
||||||
return device->IOCtlV(address);
|
return device->IOCtlV(IOSIOCtlVRequest{request.address});
|
||||||
default:
|
default:
|
||||||
_assert_msg_(WII_IPC_HLE, false, "Unexpected command: %x", command);
|
_assert_msg_(WII_IPC_HLE, false, "Unexpected command: %x", request.command);
|
||||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
return IWII_IPC_HLE_Device::GetDefaultReply(IPC_EINVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteCommand(const u32 address)
|
void ExecuteCommand(const u32 address)
|
||||||
{
|
{
|
||||||
IPCCommandResult result = HandleCommand(address);
|
IOSRequest request{address};
|
||||||
|
IPCCommandResult result = HandleCommand(request);
|
||||||
|
|
||||||
// Ensure replies happen in order
|
// Ensure replies happen in order
|
||||||
const s64 ticks_until_last_reply = s_last_reply_time - CoreTiming::GetTicks();
|
const s64 ticks_until_last_reply = s_last_reply_time - CoreTiming::GetTicks();
|
||||||
|
@ -443,7 +434,7 @@ void ExecuteCommand(const u32 address)
|
||||||
s_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
|
s_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
|
||||||
|
|
||||||
if (result.send_reply)
|
if (result.send_reply)
|
||||||
EnqueueReply(address, static_cast<int>(result.reply_delay_ticks));
|
EnqueueReply(request, result.return_value, static_cast<int>(result.reply_delay_ticks));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Happens AS SOON AS IPC gets a new pointer!
|
// Happens AS SOON AS IPC gets a new pointer!
|
||||||
|
@ -453,13 +444,15 @@ void EnqueueRequest(u32 address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called to send a reply to an IOS syscall
|
// Called to send a reply to an IOS syscall
|
||||||
void EnqueueReply(u32 address, int cycles_in_future, CoreTiming::FromThread from)
|
void EnqueueReply(const IOSRequest& request, const s32 return_value, int cycles_in_future,
|
||||||
|
CoreTiming::FromThread from)
|
||||||
{
|
{
|
||||||
|
Memory::Write_U32(static_cast<u32>(return_value), request.address + 4);
|
||||||
// IOS writes back the command that was responded to in the FD field.
|
// IOS writes back the command that was responded to in the FD field.
|
||||||
Memory::Write_U32(Memory::Read_U32(address), address + 8);
|
Memory::Write_U32(request.command, request.address + 8);
|
||||||
// IOS also overwrites the command type with the reply type.
|
// IOS also overwrites the command type with the reply type.
|
||||||
Memory::Write_U32(IPC_REPLY, address);
|
Memory::Write_U32(IPC_REPLY, request.address);
|
||||||
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, address, from);
|
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
|
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
|
||||||
|
|
|
@ -12,11 +12,13 @@
|
||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
|
|
||||||
|
struct IOSRequest;
|
||||||
class IWII_IPC_HLE_Device;
|
class IWII_IPC_HLE_Device;
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
|
||||||
struct IPCCommandResult
|
struct IPCCommandResult
|
||||||
{
|
{
|
||||||
|
s32 return_value;
|
||||||
bool send_reply;
|
bool send_reply;
|
||||||
u64 reply_delay_ticks;
|
u64 reply_delay_ticks;
|
||||||
};
|
};
|
||||||
|
@ -69,7 +71,7 @@ void UpdateDevices();
|
||||||
void ExecuteCommand(u32 address);
|
void ExecuteCommand(u32 address);
|
||||||
|
|
||||||
void EnqueueRequest(u32 address);
|
void EnqueueRequest(u32 address);
|
||||||
void EnqueueReply(u32 address, int cycles_in_future = 0,
|
void EnqueueReply(const IOSRequest& request, s32 return_value, int cycles_in_future = 0,
|
||||||
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
||||||
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
|
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
|
||||||
|
|
||||||
|
|
|
@ -2,48 +2,119 @@
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
|
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
|
||||||
|
|
||||||
SIOCtlVBuffer::SIOCtlVBuffer(const u32 address) : m_Address(address)
|
IOSRequest::IOSRequest(const u32 address_) : address(address_)
|
||||||
{
|
{
|
||||||
// These are the Ioctlv parameters in the IOS communication. The BufferVector
|
command = static_cast<IPCCommandType>(Memory::Read_U32(address));
|
||||||
// is a memory address offset at where the in and out buffer addresses are
|
fd = Memory::Read_U32(address + 8);
|
||||||
// stored.
|
}
|
||||||
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
|
|
||||||
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
|
|
||||||
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
|
|
||||||
BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3
|
|
||||||
|
|
||||||
// The start of the out buffer
|
IOSOpenRequest::IOSOpenRequest(const u32 address_) : IOSRequest(address_)
|
||||||
u32 BufferVectorOffset = BufferVector;
|
{
|
||||||
|
path = Memory::GetString(Memory::Read_U32(address + 0xc));
|
||||||
|
flags = static_cast<IOSOpenMode>(Memory::Read_U32(address + 0x10));
|
||||||
|
}
|
||||||
|
|
||||||
// Write the address and size for all in messages
|
IOSReadWriteRequest::IOSReadWriteRequest(const u32 address_) : IOSRequest(address_)
|
||||||
for (u32 i = 0; i < NumberInBuffer; i++)
|
{
|
||||||
|
buffer = Memory::Read_U32(address + 0xc);
|
||||||
|
size = Memory::Read_U32(address + 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOSSeekRequest::IOSSeekRequest(const u32 address_) : IOSRequest(address_)
|
||||||
|
{
|
||||||
|
offset = Memory::Read_U32(address + 0xc);
|
||||||
|
mode = static_cast<SeekMode>(Memory::Read_U32(address + 0x10));
|
||||||
|
}
|
||||||
|
|
||||||
|
IOSIOCtlRequest::IOSIOCtlRequest(const u32 address_) : IOSRequest(address_)
|
||||||
|
{
|
||||||
|
request = Memory::Read_U32(address + 0x0c);
|
||||||
|
buffer_in = Memory::Read_U32(address + 0x10);
|
||||||
|
buffer_in_size = Memory::Read_U32(address + 0x14);
|
||||||
|
buffer_out = Memory::Read_U32(address + 0x18);
|
||||||
|
buffer_out_size = Memory::Read_U32(address + 0x1c);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOSIOCtlVRequest::IOSIOCtlVRequest(const u32 address_) : IOSRequest(address_)
|
||||||
|
{
|
||||||
|
request = Memory::Read_U32(address + 0x0c);
|
||||||
|
const u32 in_number = Memory::Read_U32(address + 0x10);
|
||||||
|
const u32 out_number = Memory::Read_U32(address + 0x14);
|
||||||
|
const u32 vectors_base = Memory::Read_U32(address + 0x18); // address to vectors
|
||||||
|
|
||||||
|
u32 offset = 0;
|
||||||
|
for (size_t i = 0; i < (in_number + out_number); ++i)
|
||||||
{
|
{
|
||||||
SBuffer Buffer;
|
IOVector vector;
|
||||||
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
|
vector.address = Memory::Read_U32(vectors_base + offset);
|
||||||
BufferVectorOffset += 4;
|
vector.size = Memory::Read_U32(vectors_base + offset + 4);
|
||||||
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
|
offset += 8;
|
||||||
BufferVectorOffset += 4;
|
if (i < in_number)
|
||||||
InBuffer.push_back(Buffer);
|
in_vectors.emplace_back(vector);
|
||||||
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x", i, Buffer.m_Address, Buffer.m_Size);
|
else
|
||||||
|
io_vectors.emplace_back(vector);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write the address and size for all out or in-out messages
|
bool IOSIOCtlVRequest::HasInputVectorWithAddress(const u32 vector_address) const
|
||||||
for (u32 i = 0; i < NumberPayloadBuffer; i++)
|
{
|
||||||
{
|
return std::any_of(in_vectors.begin(), in_vectors.end(),
|
||||||
SBuffer Buffer;
|
[&](const auto& in_vector) { return in_vector.address == vector_address; });
|
||||||
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
|
}
|
||||||
BufferVectorOffset += 4;
|
|
||||||
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
|
void IOSIOCtlRequest::Log(const std::string& device_name, LogTypes::LOG_TYPE type,
|
||||||
BufferVectorOffset += 4;
|
LogTypes::LOG_LEVELS verbosity) const
|
||||||
PayloadBuffer.push_back(Buffer);
|
{
|
||||||
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x", i, Buffer.m_Address, Buffer.m_Size);
|
GENERIC_LOG(type, verbosity, "%s (fd %u) - IOCtl 0x%x (in_size=0x%x, out_size=0x%x)",
|
||||||
}
|
device_name.c_str(), fd, request, buffer_in_size, buffer_out_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOSIOCtlRequest::Dump(const std::string& description, LogTypes::LOG_TYPE type,
|
||||||
|
LogTypes::LOG_LEVELS level) const
|
||||||
|
{
|
||||||
|
Log("===== " + description, type, level);
|
||||||
|
GENERIC_LOG(type, level, "In buffer\n%s",
|
||||||
|
HexDump(Memory::GetPointer(buffer_in), buffer_in_size).c_str());
|
||||||
|
GENERIC_LOG(type, level, "Out buffer\n%s",
|
||||||
|
HexDump(Memory::GetPointer(buffer_out), buffer_out_size).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOSIOCtlRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type,
|
||||||
|
LogTypes::LOG_LEVELS level) const
|
||||||
|
{
|
||||||
|
Dump("Unknown IOCtl - " + description, type, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOSIOCtlVRequest::Dump(const std::string& description, LogTypes::LOG_TYPE type,
|
||||||
|
LogTypes::LOG_LEVELS level) const
|
||||||
|
{
|
||||||
|
GENERIC_LOG(type, level, "===== %s (fd %u) - IOCtlV 0x%x (%zu in, %zu io)", description.c_str(),
|
||||||
|
fd, request, in_vectors.size(), io_vectors.size());
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto& vector : in_vectors)
|
||||||
|
GENERIC_LOG(type, level, "in[%zu] (size=0x%x):\n%s", i++, vector.size,
|
||||||
|
HexDump(Memory::GetPointer(vector.address), vector.size).c_str());
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (const auto& vector : io_vectors)
|
||||||
|
GENERIC_LOG(type, level, "io[%zu] (size=0x%x)", i++, vector.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOSIOCtlVRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type,
|
||||||
|
LogTypes::LOG_LEVELS level) const
|
||||||
|
{
|
||||||
|
Dump("Unknown IOCtlV - " + description, type, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
IWII_IPC_HLE_Device::IWII_IPC_HLE_Device(const u32 device_id, const std::string& device_name,
|
IWII_IPC_HLE_Device::IWII_IPC_HLE_Device(const u32 device_id, const std::string& device_name,
|
||||||
|
@ -66,116 +137,37 @@ void IWII_IPC_HLE_Device::DoStateShared(PointerWrap& p)
|
||||||
p.Do(m_is_active);
|
p.Do(m_is_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::Open(u32 command_address, u32 mode)
|
IOSReturnCode IWII_IPC_HLE_Device::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetDefaultReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::Close(u32 command_address, bool force)
|
void IWII_IPC_HLE_Device::Close()
|
||||||
{
|
{
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::Seek(u32 command_address)
|
IPCCommandResult IWII_IPC_HLE_Device::Unsupported(const IOSRequest& request)
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_HLE, "%s does not support Seek()", m_name.c_str());
|
static std::map<IPCCommandType, std::string> names = {{{IPC_CMD_READ, "Read"},
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address);
|
{IPC_CMD_WRITE, "Write"},
|
||||||
return GetDefaultReply();
|
{IPC_CMD_SEEK, "Seek"},
|
||||||
}
|
{IPC_CMD_IOCTL, "IOCtl"},
|
||||||
|
{IPC_CMD_IOCTLV, "IOCtlV"}}};
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::Read(u32 command_address)
|
WARN_LOG(WII_IPC_HLE, "%s does not support %s()", m_name.c_str(), names[request.command].c_str());
|
||||||
{
|
return GetDefaultReply(IPC_EINVAL);
|
||||||
WARN_LOG(WII_IPC_HLE, "%s does not support Read()", m_name.c_str());
|
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::Write(u32 command_address)
|
|
||||||
{
|
|
||||||
WARN_LOG(WII_IPC_HLE, "%s does not support Write()", m_name.c_str());
|
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::IOCtl(u32 command_address)
|
|
||||||
{
|
|
||||||
WARN_LOG(WII_IPC_HLE, "%s does not support IOCtl()", m_name.c_str());
|
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::IOCtlV(u32 command_address)
|
|
||||||
{
|
|
||||||
WARN_LOG(WII_IPC_HLE, "%s does not support IOCtlV()", m_name.c_str());
|
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an IPCCommandResult for a reply that takes 250 us (arbitrarily chosen value)
|
// Returns an IPCCommandResult for a reply that takes 250 us (arbitrarily chosen value)
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::GetDefaultReply()
|
IPCCommandResult IWII_IPC_HLE_Device::GetDefaultReply(const s32 return_value)
|
||||||
{
|
{
|
||||||
return {true, SystemTimers::GetTicksPerSecond() / 4000};
|
return {return_value, true, SystemTimers::GetTicksPerSecond() / 4000};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an IPCCommandResult with no reply. Useful for async commands that will generate a reply
|
// Returns an IPCCommandResult with no reply. Useful for async commands that will generate a reply
|
||||||
// later
|
// later. This takes no return value because it won't be used.
|
||||||
IPCCommandResult IWII_IPC_HLE_Device::GetNoReply()
|
IPCCommandResult IWII_IPC_HLE_Device::GetNoReply()
|
||||||
{
|
{
|
||||||
return {false, 0};
|
return {IPC_SUCCESS, false, 0};
|
||||||
}
|
|
||||||
|
|
||||||
// Write out the IPC struct from command_address to num_commands numbers
|
|
||||||
// of 4 byte commands.
|
|
||||||
void IWII_IPC_HLE_Device::DumpCommands(u32 command_address, size_t num_commands,
|
|
||||||
LogTypes::LOG_TYPE log_type, LogTypes::LOG_LEVELS verbosity)
|
|
||||||
{
|
|
||||||
GENERIC_LOG(log_type, verbosity, "CommandDump of %s", GetDeviceName().c_str());
|
|
||||||
for (u32 i = 0; i < num_commands; i++)
|
|
||||||
{
|
|
||||||
GENERIC_LOG(log_type, verbosity, " Command%02i: 0x%08x", i,
|
|
||||||
Memory::Read_U32(command_address + i * 4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IWII_IPC_HLE_Device::DumpAsync(u32 buffer_vector, u32 number_in_buffer, u32 number_io_buffer,
|
|
||||||
LogTypes::LOG_TYPE log_type, LogTypes::LOG_LEVELS verbosity)
|
|
||||||
{
|
|
||||||
GENERIC_LOG(log_type, verbosity, "======= DumpAsync ======");
|
|
||||||
|
|
||||||
u32 BufferOffset = buffer_vector;
|
|
||||||
for (u32 i = 0; i < number_in_buffer; i++)
|
|
||||||
{
|
|
||||||
u32 InBuffer = Memory::Read_U32(BufferOffset);
|
|
||||||
BufferOffset += 4;
|
|
||||||
u32 InBufferSize = Memory::Read_U32(BufferOffset);
|
|
||||||
BufferOffset += 4;
|
|
||||||
|
|
||||||
GENERIC_LOG(log_type, LogTypes::LINFO, "%s - IOCtlV InBuffer[%i]:", GetDeviceName().c_str(), i);
|
|
||||||
|
|
||||||
std::string Temp;
|
|
||||||
for (u32 j = 0; j < InBufferSize; j++)
|
|
||||||
{
|
|
||||||
Temp += StringFromFormat("%02x ", Memory::Read_U8(InBuffer + j));
|
|
||||||
}
|
|
||||||
|
|
||||||
GENERIC_LOG(log_type, LogTypes::LDEBUG, " Buffer: %s", Temp.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < number_io_buffer; i++)
|
|
||||||
{
|
|
||||||
u32 OutBuffer = Memory::Read_U32(BufferOffset);
|
|
||||||
BufferOffset += 4;
|
|
||||||
u32 OutBufferSize = Memory::Read_U32(BufferOffset);
|
|
||||||
BufferOffset += 4;
|
|
||||||
|
|
||||||
GENERIC_LOG(log_type, LogTypes::LINFO, "%s - IOCtlV OutBuffer[%i]:", GetDeviceName().c_str(),
|
|
||||||
i);
|
|
||||||
GENERIC_LOG(log_type, LogTypes::LINFO, " OutBuffer: 0x%08x (0x%x):", OutBuffer,
|
|
||||||
OutBufferSize);
|
|
||||||
|
|
||||||
if (verbosity >= LogTypes::LOG_LEVELS::LINFO)
|
|
||||||
DumpCommands(OutBuffer, OutBufferSize, log_type, verbosity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||||
|
|
||||||
enum IOSReturnCode : s32
|
enum IOSReturnCode : s32
|
||||||
|
@ -41,22 +40,88 @@ enum IOSReturnCode : s32
|
||||||
IPC_EESEXHAUSTED = -1016, // Max of 2 ES handles exceeded
|
IPC_EESEXHAUSTED = -1016, // Max of 2 ES handles exceeded
|
||||||
};
|
};
|
||||||
|
|
||||||
// A struct for IOS ioctlv calls
|
struct IOSRequest
|
||||||
struct SIOCtlVBuffer
|
|
||||||
{
|
{
|
||||||
explicit SIOCtlVBuffer(u32 address);
|
u32 address = 0;
|
||||||
|
IPCCommandType command = IPC_CMD_OPEN;
|
||||||
|
u32 fd = 0;
|
||||||
|
explicit IOSRequest(u32 address);
|
||||||
|
virtual ~IOSRequest() = default;
|
||||||
|
};
|
||||||
|
|
||||||
const u32 m_Address;
|
enum IOSOpenMode : s32
|
||||||
u32 Parameter;
|
{
|
||||||
u32 NumberInBuffer;
|
IOS_OPEN_READ = 1,
|
||||||
u32 NumberPayloadBuffer;
|
IOS_OPEN_WRITE = 2,
|
||||||
u32 BufferVector;
|
IOS_OPEN_RW = (IOS_OPEN_READ | IOS_OPEN_WRITE)
|
||||||
struct SBuffer
|
};
|
||||||
|
|
||||||
|
struct IOSOpenRequest final : IOSRequest
|
||||||
|
{
|
||||||
|
std::string path;
|
||||||
|
IOSOpenMode flags = IOS_OPEN_READ;
|
||||||
|
explicit IOSOpenRequest(u32 address);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IOSReadWriteRequest final : IOSRequest
|
||||||
|
{
|
||||||
|
u32 buffer = 0;
|
||||||
|
u32 size = 0;
|
||||||
|
explicit IOSReadWriteRequest(u32 address);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IOSSeekRequest final : IOSRequest
|
||||||
|
{
|
||||||
|
enum SeekMode
|
||||||
{
|
{
|
||||||
u32 m_Address, m_Size;
|
IOS_SEEK_SET = 0,
|
||||||
|
IOS_SEEK_CUR = 1,
|
||||||
|
IOS_SEEK_END = 2,
|
||||||
};
|
};
|
||||||
std::vector<SBuffer> InBuffer;
|
u32 offset = 0;
|
||||||
std::vector<SBuffer> PayloadBuffer;
|
SeekMode mode = IOS_SEEK_SET;
|
||||||
|
explicit IOSSeekRequest(u32 address);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IOSIOCtlRequest final : IOSRequest
|
||||||
|
{
|
||||||
|
u32 request = 0;
|
||||||
|
u32 buffer_in = 0;
|
||||||
|
u32 buffer_in_size = 0;
|
||||||
|
// Contrary to the name, the output buffer can also be used for input.
|
||||||
|
u32 buffer_out = 0;
|
||||||
|
u32 buffer_out_size = 0;
|
||||||
|
explicit IOSIOCtlRequest(u32 address);
|
||||||
|
void Log(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
|
||||||
|
LogTypes::LOG_LEVELS level = LogTypes::LINFO) const;
|
||||||
|
void Dump(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
|
||||||
|
LogTypes::LOG_LEVELS level = LogTypes::LINFO) const;
|
||||||
|
void DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
|
||||||
|
LogTypes::LOG_LEVELS level = LogTypes::LERROR) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IOSIOCtlVRequest final : IOSRequest
|
||||||
|
{
|
||||||
|
struct IOVector
|
||||||
|
{
|
||||||
|
u32 address = 0;
|
||||||
|
u32 size = 0;
|
||||||
|
};
|
||||||
|
u32 request = 0;
|
||||||
|
// In vectors are *mostly* used for input buffers. Sometimes they are also used as
|
||||||
|
// output buffers (notably in the network code).
|
||||||
|
// IO vectors are *mostly* used for output buffers. However, as indicated in the name,
|
||||||
|
// they're also used as input buffers.
|
||||||
|
// So both of them are technically IO vectors. But we're keeping them separated because
|
||||||
|
// merging them into a single std::vector would make using the first out vector more complicated.
|
||||||
|
std::vector<IOVector> in_vectors;
|
||||||
|
std::vector<IOVector> io_vectors;
|
||||||
|
explicit IOSIOCtlVRequest(u32 address);
|
||||||
|
bool HasInputVectorWithAddress(u32 vector_address) const;
|
||||||
|
void Dump(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
|
||||||
|
LogTypes::LOG_LEVELS level = LogTypes::LINFO) const;
|
||||||
|
void DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
|
||||||
|
LogTypes::LOG_LEVELS level = LogTypes::LERROR) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IWII_IPC_HLE_Device
|
class IWII_IPC_HLE_Device
|
||||||
|
@ -79,18 +144,18 @@ public:
|
||||||
|
|
||||||
const std::string& GetDeviceName() const { return m_name; }
|
const std::string& GetDeviceName() const { return m_name; }
|
||||||
u32 GetDeviceID() const { return m_device_id; }
|
u32 GetDeviceID() const { return m_device_id; }
|
||||||
virtual IPCCommandResult Open(u32 command_address, u32 mode);
|
// Replies to Open and Close requests are sent by WII_IPC_HLE, not by the devices themselves.
|
||||||
virtual IPCCommandResult Close(u32 command_address, bool force = false);
|
virtual IOSReturnCode Open(const IOSOpenRequest& request);
|
||||||
virtual IPCCommandResult Seek(u32 command_address);
|
virtual void Close();
|
||||||
virtual IPCCommandResult Read(u32 command_address);
|
virtual IPCCommandResult Seek(const IOSSeekRequest& seek) { return Unsupported(seek); }
|
||||||
virtual IPCCommandResult Write(u32 command_address);
|
virtual IPCCommandResult Read(const IOSReadWriteRequest& read) { return Unsupported(read); }
|
||||||
virtual IPCCommandResult IOCtl(u32 command_address);
|
virtual IPCCommandResult Write(const IOSReadWriteRequest& write) { return Unsupported(write); }
|
||||||
virtual IPCCommandResult IOCtlV(u32 command_address);
|
virtual IPCCommandResult IOCtl(const IOSIOCtlRequest& ioctl) { return Unsupported(ioctl); }
|
||||||
|
virtual IPCCommandResult IOCtlV(const IOSIOCtlVRequest& ioctlv) { return Unsupported(ioctlv); }
|
||||||
virtual void Update() {}
|
virtual void Update() {}
|
||||||
virtual DeviceType GetDeviceType() const { return m_device_type; }
|
virtual DeviceType GetDeviceType() const { return m_device_type; }
|
||||||
virtual bool IsOpened() const { return m_is_active; }
|
virtual bool IsOpened() const { return m_is_active; }
|
||||||
static IPCCommandResult GetDefaultReply();
|
static IPCCommandResult GetDefaultReply(s32 return_value);
|
||||||
static IPCCommandResult GetNoReply();
|
static IPCCommandResult GetNoReply();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -100,13 +165,6 @@ protected:
|
||||||
DeviceType m_device_type;
|
DeviceType m_device_type;
|
||||||
bool m_is_active = false;
|
bool m_is_active = false;
|
||||||
|
|
||||||
// Write out the IPC struct from command_address to number_of_commands numbers
|
private:
|
||||||
// of 4 byte commands.
|
IPCCommandResult Unsupported(const IOSRequest& request);
|
||||||
void DumpCommands(u32 command_address, size_t number_of_commands = 8,
|
|
||||||
LogTypes::LOG_TYPE log_type = LogTypes::WII_IPC_HLE,
|
|
||||||
LogTypes::LOG_LEVELS verbosity = LogTypes::LDEBUG);
|
|
||||||
|
|
||||||
void DumpAsync(u32 buffer_vector, u32 number_in_buffer, u32 number_io_buffer,
|
|
||||||
LogTypes::LOG_TYPE log_type = LogTypes::WII_IPC_HLE,
|
|
||||||
LogTypes::LOG_LEVELS verbosity = LogTypes::LDEBUG);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ void CWII_IPC_HLE_Device_di::DoState(PointerWrap& p)
|
||||||
p.Do(m_commands_to_execute);
|
p.Do(m_commands_to_execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
// DI IOCtls are handled in a special way by Dolphin
|
// DI IOCtls are handled in a special way by Dolphin
|
||||||
// compared to other WII_IPC_HLE functions.
|
// compared to other WII_IPC_HLE functions.
|
||||||
|
@ -42,40 +42,25 @@ IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress)
|
||||||
// are queued until DVDInterface is ready to handle them.
|
// are queued until DVDInterface is ready to handle them.
|
||||||
|
|
||||||
bool ready_to_execute = m_commands_to_execute.empty();
|
bool ready_to_execute = m_commands_to_execute.empty();
|
||||||
m_commands_to_execute.push_back(_CommandAddress);
|
m_commands_to_execute.push_back(request.address);
|
||||||
if (ready_to_execute)
|
if (ready_to_execute)
|
||||||
StartIOCtl(_CommandAddress);
|
StartIOCtl(request);
|
||||||
|
|
||||||
// DVDInterface handles the timing and we handle the reply,
|
// DVDInterface handles the timing and we handle the reply,
|
||||||
// so WII_IPC_HLE shouldn't handle anything.
|
// so WII_IPC_HLE shouldn't handle anything.
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_di::StartIOCtl(u32 command_address)
|
void CWII_IPC_HLE_Device_di::StartIOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
u32 BufferIn = Memory::Read_U32(command_address + 0x10);
|
const u32 command_0 = Memory::Read_U32(request.buffer_in);
|
||||||
u32 BufferInSize = Memory::Read_U32(command_address + 0x14);
|
const u32 command_1 = Memory::Read_U32(request.buffer_in + 4);
|
||||||
u32 BufferOut = Memory::Read_U32(command_address + 0x18);
|
const u32 command_2 = Memory::Read_U32(request.buffer_in + 8);
|
||||||
u32 BufferOutSize = Memory::Read_U32(command_address + 0x1C);
|
|
||||||
|
|
||||||
u32 command_0 = Memory::Read_U32(BufferIn);
|
|
||||||
u32 command_1 = Memory::Read_U32(BufferIn + 4);
|
|
||||||
u32 command_2 = Memory::Read_U32(BufferIn + 8);
|
|
||||||
|
|
||||||
DEBUG_LOG(WII_IPC_DVD, "IOCtl Command(0x%08x) BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)",
|
|
||||||
command_0, BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
|
|
||||||
// TATSUNOKO VS CAPCOM: Gets here with BufferOut == 0!!!
|
|
||||||
if (BufferOut != 0)
|
|
||||||
{
|
|
||||||
// Set out buffer to zeroes as a safety precaution
|
|
||||||
// to avoid answering nonsense values
|
|
||||||
Memory::Memset(BufferOut, 0, BufferOutSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DVDInterface's ExecuteCommand handles most of the work.
|
// DVDInterface's ExecuteCommand handles most of the work.
|
||||||
// The IOCtl callback is used to generate a reply afterwards.
|
// The IOCtl callback is used to generate a reply afterwards.
|
||||||
DVDInterface::ExecuteCommand(command_0, command_1, command_2, BufferOut, BufferOutSize, true);
|
DVDInterface::ExecuteCommand(command_0, command_1, command_2, request.buffer_out,
|
||||||
|
request.buffer_out_size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type)
|
void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type)
|
||||||
|
@ -89,58 +74,46 @@ void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt
|
||||||
// This command has been executed, so it's removed from the queue
|
// This command has been executed, so it's removed from the queue
|
||||||
u32 command_address = m_commands_to_execute.front();
|
u32 command_address = m_commands_to_execute.front();
|
||||||
m_commands_to_execute.pop_front();
|
m_commands_to_execute.pop_front();
|
||||||
|
WII_IPC_HLE_Interface::EnqueueReply(IOSIOCtlRequest{command_address}, interrupt_type);
|
||||||
// The DI interrupt type is used as a return value
|
|
||||||
Memory::Write_U32(interrupt_type, command_address + 4);
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(command_address);
|
|
||||||
|
|
||||||
// DVDInterface is now ready to execute another command,
|
// DVDInterface is now ready to execute another command,
|
||||||
// so we start executing a command from the queue if there is one
|
// so we start executing a command from the queue if there is one
|
||||||
if (!m_commands_to_execute.empty())
|
if (!m_commands_to_execute.empty())
|
||||||
StartIOCtl(m_commands_to_execute.front());
|
{
|
||||||
|
IOSIOCtlRequest next_request{m_commands_to_execute.front()};
|
||||||
|
StartIOCtl(next_request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
for (const auto& vector : request.io_vectors)
|
||||||
|
Memory::Memset(vector.address, 0, vector.size);
|
||||||
// Prepare the out buffer(s) with zeros as a safety precaution
|
s32 return_value = IPC_SUCCESS;
|
||||||
// to avoid returning bad values
|
switch (request.request)
|
||||||
for (const auto& buffer : CommandBuffer.PayloadBuffer)
|
|
||||||
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
|
|
||||||
|
|
||||||
u32 ReturnValue = 0;
|
|
||||||
switch (CommandBuffer.Parameter)
|
|
||||||
{
|
{
|
||||||
case DVDInterface::DVDLowOpenPartition:
|
case DVDInterface::DVDLowOpenPartition:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[1].m_Address == 0,
|
_dbg_assert_msg_(WII_IPC_DVD, request.in_vectors[1].address == 0,
|
||||||
"DVDLowOpenPartition with ticket");
|
"DVDLowOpenPartition with ticket");
|
||||||
_dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[2].m_Address == 0,
|
_dbg_assert_msg_(WII_IPC_DVD, request.in_vectors[2].address == 0,
|
||||||
"DVDLowOpenPartition with cert chain");
|
"DVDLowOpenPartition with cert chain");
|
||||||
|
|
||||||
u64 const partition_offset =
|
u64 const partition_offset = ((u64)Memory::Read_U32(request.in_vectors[0].address + 4) << 2);
|
||||||
((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2);
|
|
||||||
DVDInterface::ChangePartition(partition_offset);
|
DVDInterface::ChangePartition(partition_offset);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset);
|
INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset);
|
||||||
|
|
||||||
// Read TMD to the buffer
|
// Read TMD to the buffer
|
||||||
std::vector<u8> tmd_buffer = DVDInterface::GetVolume().GetTMD();
|
std::vector<u8> tmd_buffer = DVDInterface::GetVolume().GetTMD();
|
||||||
Memory::CopyToEmu(CommandBuffer.PayloadBuffer[0].m_Address, tmd_buffer.data(),
|
Memory::CopyToEmu(request.io_vectors[0].address, tmd_buffer.data(), tmd_buffer.size());
|
||||||
tmd_buffer.size());
|
|
||||||
WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer);
|
WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer);
|
||||||
|
|
||||||
ReturnValue = 1;
|
return_value = 1;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ERROR_LOG(WII_IPC_DVD, "IOCtlV: %i", CommandBuffer.Parameter);
|
|
||||||
_dbg_assert_msg_(WII_IPC_DVD, 0, "IOCtlV: %i", CommandBuffer.Parameter);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_DVD);
|
||||||
return GetDefaultReply();
|
}
|
||||||
|
return GetDefaultReply(return_value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,13 @@ public:
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
|
||||||
void FinishIOCtl(DVDInterface::DIInterruptType interrupt_type);
|
void FinishIOCtl(DVDInterface::DIInterruptType interrupt_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void StartIOCtl(u32 command_address);
|
void StartIOCtl(const IOSIOCtlRequest& request);
|
||||||
|
|
||||||
std::deque<u32> m_commands_to_execute;
|
std::deque<u32> m_commands_to_execute;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -70,11 +71,7 @@ CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 device_id,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_FileIO::~CWII_IPC_HLE_Device_FileIO()
|
void CWII_IPC_HLE_Device_FileIO::Close()
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress, bool _bForce)
|
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id);
|
INFO_LOG(WII_IPC_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id);
|
||||||
m_Mode = 0;
|
m_Mode = 0;
|
||||||
|
@ -84,12 +81,11 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress, bool _bF
|
||||||
m_file.reset();
|
m_file.reset();
|
||||||
|
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Open(u32 command_address, u32 mode)
|
IOSReturnCode CWII_IPC_HLE_Device_FileIO::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
m_Mode = mode;
|
m_Mode = request.flags;
|
||||||
|
|
||||||
static const char* const Modes[] = {"Unk Mode", "Read only", "Write only", "Read and Write"};
|
static const char* const Modes[] = {"Unk Mode", "Read only", "Write only", "Read and Write"};
|
||||||
|
|
||||||
|
@ -97,21 +93,18 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Open(u32 command_address, u32 mode)
|
||||||
|
|
||||||
// The file must exist before we can open it
|
// The file must exist before we can open it
|
||||||
// It should be created by ISFS_CreateFile, not here
|
// It should be created by ISFS_CreateFile, not here
|
||||||
if (File::Exists(m_filepath) && !File::IsDirectory(m_filepath))
|
if (!File::Exists(m_filepath) || File::IsDirectory(m_filepath))
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_name.c_str(), Modes[mode], mode);
|
WARN_LOG(WII_IPC_FILEIO, "FileIO: Open (%s) failed - File doesn't exist %s", Modes[m_Mode],
|
||||||
OpenFile();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WARN_LOG(WII_IPC_FILEIO, "FileIO: Open (%s) failed - File doesn't exist %s", Modes[mode],
|
|
||||||
m_filepath.c_str());
|
m_filepath.c_str());
|
||||||
if (command_address)
|
return FS_ENOENT;
|
||||||
Memory::Write_U32(FS_ENOENT, command_address + 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_name.c_str(), Modes[m_Mode], m_Mode);
|
||||||
|
OpenFile();
|
||||||
|
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetDefaultReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This isn't theadsafe, but it's only called from the CPU thread.
|
// This isn't theadsafe, but it's only called from the CPU thread.
|
||||||
|
@ -158,98 +151,90 @@ void CWII_IPC_HLE_Device_FileIO::OpenFile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Seek(const IOSSeekRequest& request)
|
||||||
{
|
{
|
||||||
u32 ReturnValue = FS_EINVAL;
|
u32 return_value = FS_EINVAL;
|
||||||
const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
|
|
||||||
const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
|
|
||||||
|
|
||||||
if (m_file->IsOpen())
|
if (m_file->IsOpen())
|
||||||
{
|
{
|
||||||
ReturnValue = FS_EINVAL;
|
const u32 file_size = static_cast<u32>(m_file->GetSize());
|
||||||
|
|
||||||
const s32 fileSize = (s32)m_file->GetSize();
|
|
||||||
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08x)",
|
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08x)",
|
||||||
SeekPosition, Mode, m_name.c_str(), fileSize);
|
request.offset, request.mode, m_name.c_str(), file_size);
|
||||||
|
|
||||||
switch (Mode)
|
switch (request.mode)
|
||||||
{
|
{
|
||||||
case WII_SEEK_SET:
|
case IOSSeekRequest::IOS_SEEK_SET:
|
||||||
{
|
{
|
||||||
if ((SeekPosition >= 0) && (SeekPosition <= fileSize))
|
if (request.offset <= file_size)
|
||||||
{
|
{
|
||||||
m_SeekPos = SeekPosition;
|
m_SeekPos = request.offset;
|
||||||
ReturnValue = m_SeekPos;
|
return_value = m_SeekPos;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WII_SEEK_CUR:
|
case IOSSeekRequest::IOS_SEEK_CUR:
|
||||||
{
|
{
|
||||||
s32 wantedPos = SeekPosition + m_SeekPos;
|
const u32 wanted_pos = request.offset + m_SeekPos;
|
||||||
if (wantedPos >= 0 && wantedPos <= fileSize)
|
if (wanted_pos <= file_size)
|
||||||
{
|
{
|
||||||
m_SeekPos = wantedPos;
|
m_SeekPos = wanted_pos;
|
||||||
ReturnValue = m_SeekPos;
|
return_value = m_SeekPos;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WII_SEEK_END:
|
case IOSSeekRequest::IOS_SEEK_END:
|
||||||
{
|
{
|
||||||
s32 wantedPos = SeekPosition + fileSize;
|
const u32 wanted_pos = request.offset + file_size;
|
||||||
if (wantedPos >= 0 && wantedPos <= fileSize)
|
if (wanted_pos <= file_size)
|
||||||
{
|
{
|
||||||
m_SeekPos = wantedPos;
|
m_SeekPos = wanted_pos;
|
||||||
ReturnValue = m_SeekPos;
|
return_value = m_SeekPos;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", Mode);
|
PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", request.mode);
|
||||||
ReturnValue = FS_EINVAL;
|
return_value = FS_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReturnValue = FS_ENOENT;
|
return_value = FS_ENOENT;
|
||||||
}
|
}
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
return GetDefaultReply(return_value);
|
||||||
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Read(const IOSReadWriteRequest& request)
|
||||||
{
|
{
|
||||||
u32 ReturnValue = FS_EACCESS;
|
s32 return_value = FS_EACCESS;
|
||||||
const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Read to this memory address
|
|
||||||
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
|
|
||||||
|
|
||||||
if (m_file->IsOpen())
|
if (m_file->IsOpen())
|
||||||
{
|
{
|
||||||
if (m_Mode == ISFS_OPEN_WRITE)
|
if (m_Mode == IOS_OPEN_WRITE)
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO,
|
WARN_LOG(WII_IPC_FILEIO,
|
||||||
"FileIO: Attempted to read 0x%x bytes to 0x%08x on a write-only file %s", Size,
|
"FileIO: Attempted to read 0x%x bytes to 0x%08x on a write-only file %s",
|
||||||
Address, m_name.c_str());
|
request.size, request.buffer, m_name.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", Size, Address,
|
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", request.size,
|
||||||
m_name.c_str());
|
request.buffer, m_name.c_str());
|
||||||
m_file->Seek(m_SeekPos, SEEK_SET); // File might be opened twice, need to seek before we read
|
m_file->Seek(m_SeekPos, SEEK_SET); // File might be opened twice, need to seek before we read
|
||||||
ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_file->GetHandle());
|
return_value = static_cast<u32>(
|
||||||
if (ReturnValue != Size && ferror(m_file->GetHandle()))
|
fread(Memory::GetPointer(request.buffer), 1, request.size, m_file->GetHandle()));
|
||||||
|
if (static_cast<u32>(return_value) != request.size && ferror(m_file->GetHandle()))
|
||||||
{
|
{
|
||||||
ReturnValue = FS_EACCESS;
|
return_value = FS_EACCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_SeekPos += Size;
|
m_SeekPos += request.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,39 +242,34 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could "
|
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could "
|
||||||
"not be opened or does not exist",
|
"not be opened or does not exist",
|
||||||
m_name.c_str(), Address, Size);
|
m_name.c_str(), request.buffer, request.size);
|
||||||
ReturnValue = FS_ENOENT;
|
return_value = FS_ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
return GetDefaultReply(return_value);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Write(const IOSReadWriteRequest& request)
|
||||||
{
|
{
|
||||||
u32 ReturnValue = FS_EACCESS;
|
s32 return_value = FS_EACCESS;
|
||||||
const u32 Address =
|
|
||||||
Memory::Read_U32(_CommandAddress + 0xC); // Write data from this memory address
|
|
||||||
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
|
|
||||||
|
|
||||||
if (m_file->IsOpen())
|
if (m_file->IsOpen())
|
||||||
{
|
{
|
||||||
if (m_Mode == ISFS_OPEN_READ)
|
if (m_Mode == IOS_OPEN_READ)
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO,
|
WARN_LOG(WII_IPC_FILEIO,
|
||||||
"FileIO: Attempted to write 0x%x bytes from 0x%08x to a read-only file %s", Size,
|
"FileIO: Attempted to write 0x%x bytes from 0x%08x to a read-only file %s",
|
||||||
Address, m_name.c_str());
|
request.size, request.buffer, m_name.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", Size, Address,
|
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", request.size,
|
||||||
m_name.c_str());
|
request.buffer, m_name.c_str());
|
||||||
m_file->Seek(m_SeekPos,
|
m_file->Seek(m_SeekPos,
|
||||||
SEEK_SET); // File might be opened twice, need to seek before we write
|
SEEK_SET); // File might be opened twice, need to seek before we write
|
||||||
if (m_file->WriteBytes(Memory::GetPointer(Address), Size))
|
if (m_file->WriteBytes(Memory::GetPointer(request.buffer), request.size))
|
||||||
{
|
{
|
||||||
ReturnValue = Size;
|
return_value = request.size;
|
||||||
m_SeekPos += Size;
|
m_SeekPos += request.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,55 +277,41 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could "
|
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could "
|
||||||
"not be opened or does not exist",
|
"not be opened or does not exist",
|
||||||
m_name.c_str(), Address, Size);
|
m_name.c_str(), request.buffer, request.size);
|
||||||
ReturnValue = FS_ENOENT;
|
return_value = FS_ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
return GetDefaultReply(return_value);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_FileIO::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: IOCtl (Device=%s)", m_name.c_str());
|
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: IOCtl (Device=%s)", m_name.c_str());
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
s32 return_value = IPC_SUCCESS;
|
||||||
DumpCommands(_CommandAddress);
|
|
||||||
#endif
|
|
||||||
const u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
|
|
||||||
u32 ReturnValue = 0;
|
|
||||||
|
|
||||||
switch (Parameter)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
case ISFS_IOCTL_GETFILESTATS:
|
case ISFS_IOCTL_GETFILESTATS:
|
||||||
{
|
{
|
||||||
if (m_file->IsOpen())
|
if (m_file->IsOpen())
|
||||||
{
|
{
|
||||||
u32 m_FileLength = (u32)m_file->GetSize();
|
DEBUG_LOG(WII_IPC_FILEIO, "File: %s, Length: %" PRIu64 ", Pos: %i", m_name.c_str(),
|
||||||
|
m_file->GetSize(), m_SeekPos);
|
||||||
const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
Memory::Write_U32(static_cast<u32>(m_file->GetSize()), request.buffer_out);
|
||||||
DEBUG_LOG(WII_IPC_FILEIO, " File: %s, Length: %i, Pos: %i", m_name.c_str(), m_FileLength,
|
Memory::Write_U32(m_SeekPos, request.buffer_out + 4);
|
||||||
m_SeekPos);
|
|
||||||
|
|
||||||
Memory::Write_U32(m_FileLength, BufferOut);
|
|
||||||
Memory::Write_U32(m_SeekPos, BufferOut + 4);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReturnValue = FS_ENOENT;
|
return_value = FS_ENOENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
request.Log(GetDeviceName(), LogTypes::WII_IPC_FILEIO, LogTypes::LERROR);
|
||||||
PanicAlert("CWII_IPC_HLE_Device_FileIO: Parameter %i", Parameter);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
return GetDefaultReply(return_value);
|
||||||
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_FileIO::PrepareForState(PointerWrap::Mode mode)
|
void CWII_IPC_HLE_Device_FileIO::PrepareForState(PointerWrap::Mode mode)
|
||||||
|
|
|
@ -26,34 +26,18 @@ class CWII_IPC_HLE_Device_FileIO : public IWII_IPC_HLE_Device
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName);
|
CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName);
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_FileIO();
|
void Close() override;
|
||||||
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
|
IPCCommandResult Seek(const IOSSeekRequest& request) override;
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
|
IPCCommandResult Read(const IOSReadWriteRequest& request) override;
|
||||||
IPCCommandResult Seek(u32 _CommandAddress) override;
|
IPCCommandResult Write(const IOSReadWriteRequest& request) override;
|
||||||
IPCCommandResult Read(u32 _CommandAddress) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult Write(u32 _CommandAddress) override;
|
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
|
||||||
void PrepareForState(PointerWrap::Mode mode) override;
|
void PrepareForState(PointerWrap::Mode mode) override;
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
void OpenFile();
|
void OpenFile();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
|
||||||
{
|
|
||||||
ISFS_OPEN_READ = 1,
|
|
||||||
ISFS_OPEN_WRITE = 2,
|
|
||||||
ISFS_OPEN_RW = (ISFS_OPEN_READ | ISFS_OPEN_WRITE)
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
WII_SEEK_SET = 0,
|
|
||||||
WII_SEEK_CUR = 1,
|
|
||||||
WII_SEEK_END = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ISFS_FUNCNULL = 0,
|
ISFS_FUNCNULL = 0,
|
||||||
|
|
|
@ -97,10 +97,6 @@ u8* CWII_IPC_HLE_Device_es::keyTable[11] = {
|
||||||
key_empty, // Unknown
|
key_empty, // Unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_es::~CWII_IPC_HLE_Device_es()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile)
|
void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile)
|
||||||
{
|
{
|
||||||
m_ContentFile = _rContentFile;
|
m_ContentFile = _rContentFile;
|
||||||
|
@ -195,17 +191,16 @@ void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
|
IOSReturnCode CWII_IPC_HLE_Device_es::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
OpenInternal();
|
OpenInternal();
|
||||||
|
|
||||||
if (m_is_active)
|
if (m_is_active)
|
||||||
INFO_LOG(WII_IPC_ES, "Device was re-opened.");
|
INFO_LOG(WII_IPC_ES, "Device was re-opened.");
|
||||||
m_is_active = true;
|
return IWII_IPC_HLE_Device::Open(request);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce)
|
void CWII_IPC_HLE_Device_es::Close()
|
||||||
{
|
{
|
||||||
m_ContentAccessMap.clear();
|
m_ContentAccessMap.clear();
|
||||||
m_TitleIDs.clear();
|
m_TitleIDs.clear();
|
||||||
|
@ -216,7 +211,6 @@ IPCCommandResult CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
// clear the NAND content cache to make sure nothing remains open.
|
// clear the NAND content cache to make sure nothing remains open.
|
||||||
DiscIO::CNANDContentManager::Access().ClearCache();
|
DiscIO::CNANDContentManager::Access().ClearCache();
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
|
u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
|
||||||
|
@ -248,54 +242,43 @@ u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
|
||||||
return CFD;
|
return CFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
SIOCtlVBuffer Buffer(_CommandAddress);
|
DEBUG_LOG(WII_IPC_ES, "%s (0x%x)", GetDeviceName().c_str(), request.request);
|
||||||
|
// Clear the IO buffers. Note that this is unsafe for other ioctlvs.
|
||||||
DEBUG_LOG(WII_IPC_ES, "%s (0x%x)", GetDeviceName().c_str(), Buffer.Parameter);
|
for (const auto& io_vector : request.io_vectors)
|
||||||
|
|
||||||
// Prepare the out buffer(s) with zeroes as a safety precaution
|
|
||||||
// to avoid returning bad values
|
|
||||||
for (const auto& buffer : Buffer.PayloadBuffer)
|
|
||||||
{
|
{
|
||||||
// Don't zero an out buffer which is also one of the in buffers.
|
if (!request.HasInputVectorWithAddress(io_vector.address))
|
||||||
if (std::any_of(Buffer.InBuffer.begin(), Buffer.InBuffer.end(),
|
Memory::Memset(io_vector.address, 0, io_vector.size);
|
||||||
[&](const auto& in_buffer) { return in_buffer.m_Address == buffer.m_Address; }))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
|
|
||||||
}
|
}
|
||||||
|
switch (request.request)
|
||||||
switch (Buffer.Parameter)
|
|
||||||
{
|
{
|
||||||
case IOCTL_ES_ADDTICKET:
|
case IOCTL_ES_ADDTICKET:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 3,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 3,
|
||||||
"IOCTL_ES_ADDTICKET wrong number of inputs");
|
"IOCTL_ES_ADDTICKET wrong number of inputs");
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTICKET");
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTICKET");
|
||||||
std::vector<u8> ticket(Buffer.InBuffer[0].m_Size);
|
std::vector<u8> ticket(request.in_vectors[0].size);
|
||||||
Memory::CopyFromEmu(ticket.data(), Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size);
|
Memory::CopyFromEmu(ticket.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
DiscIO::AddTicket(ticket);
|
DiscIO::AddTicket(ticket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IOCTL_ES_ADDTITLESTART:
|
case IOCTL_ES_ADDTITLESTART:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 4,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 4,
|
||||||
"IOCTL_ES_ADDTITLESTART wrong number of inputs");
|
"IOCTL_ES_ADDTITLESTART wrong number of inputs");
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTITLESTART");
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTITLESTART");
|
||||||
std::vector<u8> tmd(Buffer.InBuffer[0].m_Size);
|
std::vector<u8> tmd(request.in_vectors[0].size);
|
||||||
Memory::CopyFromEmu(tmd.data(), Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size);
|
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
|
|
||||||
m_addtitle_tmd.SetBytes(tmd);
|
m_addtitle_tmd.SetBytes(tmd);
|
||||||
if (!m_addtitle_tmd.IsValid())
|
if (!m_addtitle_tmd.IsValid())
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_ES, "Invalid TMD while adding title (size = %zd)", tmd.size());
|
ERROR_LOG(WII_IPC_ES, "Invalid TMD while adding title (size = %zd)", tmd.size());
|
||||||
Memory::Write_U32(ES_INVALID_TMD, _CommandAddress + 0x4);
|
return GetDefaultReply(ES_INVALID_TMD);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the TMD to title storage.
|
// Write the TMD to title storage.
|
||||||
|
@ -310,18 +293,17 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_ES_ADDCONTENTSTART:
|
case IOCTL_ES_ADDCONTENTSTART:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
|
||||||
"IOCTL_ES_ADDCONTENTSTART wrong number of inputs");
|
"IOCTL_ES_ADDCONTENTSTART wrong number of inputs");
|
||||||
|
|
||||||
u64 title_id = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
u32 content_id = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
|
||||||
|
|
||||||
if (m_addtitle_content_id != 0xFFFFFFFF)
|
if (m_addtitle_content_id != 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_ES, "Trying to add content when we haven't finished adding "
|
ERROR_LOG(WII_IPC_ES, "Trying to add content when we haven't finished adding "
|
||||||
"another content. Unsupported.");
|
"another content. Unsupported.");
|
||||||
Memory::Write_U32(ES_WRITE_FAILURE, _CommandAddress + 0x4);
|
return GetDefaultReply(ES_WRITE_FAILURE);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
m_addtitle_content_id = content_id;
|
m_addtitle_content_id = content_id;
|
||||||
|
|
||||||
|
@ -343,40 +325,38 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
// no known content installer which performs content addition concurrently.
|
// no known content installer which performs content addition concurrently.
|
||||||
// Instead we just log an error (see above) if this condition is detected.
|
// Instead we just log an error (see above) if this condition is detected.
|
||||||
s32 content_fd = 0;
|
s32 content_fd = 0;
|
||||||
Memory::Write_U32(content_fd, _CommandAddress + 0x4);
|
return GetDefaultReply(content_fd);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case IOCTL_ES_ADDCONTENTDATA:
|
case IOCTL_ES_ADDCONTENTDATA:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
|
||||||
"IOCTL_ES_ADDCONTENTDATA wrong number of inputs");
|
"IOCTL_ES_ADDCONTENTDATA wrong number of inputs");
|
||||||
|
|
||||||
u32 content_fd = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTDATA: content fd %08x, "
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTDATA: content fd %08x, "
|
||||||
"size %d",
|
"size %d",
|
||||||
content_fd, Buffer.InBuffer[1].m_Size);
|
content_fd, request.in_vectors[1].size);
|
||||||
|
|
||||||
u8* data_start = Memory::GetPointer(Buffer.InBuffer[1].m_Address);
|
u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
|
||||||
u8* data_end = data_start + Buffer.InBuffer[1].m_Size;
|
u8* data_end = data_start + request.in_vectors[1].size;
|
||||||
m_addtitle_content_buffer.insert(m_addtitle_content_buffer.end(), data_start, data_end);
|
m_addtitle_content_buffer.insert(m_addtitle_content_buffer.end(), data_start, data_end);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IOCTL_ES_ADDCONTENTFINISH:
|
case IOCTL_ES_ADDCONTENTFINISH:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
|
||||||
"IOCTL_ES_ADDCONTENTFINISH wrong number of inputs");
|
"IOCTL_ES_ADDCONTENTFINISH wrong number of inputs");
|
||||||
|
|
||||||
u32 content_fd = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTFINISH: content fd %08x", content_fd);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDCONTENTFINISH: content fd %08x", content_fd);
|
||||||
|
|
||||||
// Try to find the title key from a pre-installed ticket.
|
// Try to find the title key from a pre-installed ticket.
|
||||||
std::vector<u8> ticket = DiscIO::FindSignedTicket(m_addtitle_tmd.GetTitleId());
|
std::vector<u8> ticket = DiscIO::FindSignedTicket(m_addtitle_tmd.GetTitleId());
|
||||||
if (ticket.size() == 0)
|
if (ticket.size() == 0)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(ES_NO_TICKET_INSTALLED, _CommandAddress + 0x4);
|
return GetDefaultReply(ES_NO_TICKET_INSTALLED);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_aes_context aes_ctx;
|
mbedtls_aes_context aes_ctx;
|
||||||
|
@ -387,8 +367,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
TMDReader::Content content_info;
|
TMDReader::Content content_info;
|
||||||
if (!m_addtitle_tmd.FindContentById(m_addtitle_content_id, &content_info))
|
if (!m_addtitle_tmd.FindContentById(m_addtitle_content_id, &content_info))
|
||||||
{
|
{
|
||||||
Memory::Write_U32(ES_INVALID_TMD, _CommandAddress + 0x4);
|
return GetDefaultReply(ES_INVALID_TMD);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
u8 iv[16] = {0};
|
u8 iv[16] = {0};
|
||||||
iv[0] = (content_info.index >> 8) & 0xFF;
|
iv[0] = (content_info.index >> 8) & 0xFF;
|
||||||
|
@ -417,126 +396,122 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_ES_GETDEVICEID:
|
case IOCTL_ES_GETDEVICEID:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETDEVICEID no out buffer");
|
"IOCTL_ES_GETDEVICEID no io vectors");
|
||||||
|
|
||||||
EcWii& ec = EcWii::GetInstance();
|
EcWii& ec = EcWii::GetInstance();
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICEID %08X", ec.getNgId());
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICEID %08X", ec.getNgId());
|
||||||
Memory::Write_U32(ec.getNgId(), Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(ec.getNgId(), request.io_vectors[0].address);
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLECONTENTSCNT:
|
case IOCTL_ES_GETTITLECONTENTSCNT:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
|
|
||||||
const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID);
|
||||||
u16 NumberOfPrivateContent = 0;
|
u16 NumberOfPrivateContent = 0;
|
||||||
|
s32 return_value = IPC_SUCCESS;
|
||||||
if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check
|
if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check
|
||||||
{
|
{
|
||||||
NumberOfPrivateContent = rNANDContent.GetNumEntries();
|
NumberOfPrivateContent = rNANDContent.GetNumEntries();
|
||||||
|
|
||||||
if ((u32)(TitleID >> 32) == 0x00010000)
|
if ((u32)(TitleID >> 32) == 0x00010000)
|
||||||
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(0, request.io_vectors[0].address);
|
||||||
else
|
else
|
||||||
Memory::Write_U32(NumberOfPrivateContent, Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(NumberOfPrivateContent, request.io_vectors[0].address);
|
||||||
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Memory::Write_U32((u32)rNANDContent.GetContentSize(), _CommandAddress + 0x4);
|
{
|
||||||
|
return_value = static_cast<s32>(rNANDContent.GetContentSize());
|
||||||
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID,
|
(u32)(TitleID >> 32), (u32)TitleID,
|
||||||
rNANDContent.IsValid() ? NumberOfPrivateContent : (u32)rNANDContent.GetContentSize());
|
rNANDContent.IsValid() ? NumberOfPrivateContent : (u32)rNANDContent.GetContentSize());
|
||||||
|
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(return_value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLECONTENTS:
|
case IOCTL_ES_GETTITLECONTENTS:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
|
||||||
"IOCTL_ES_GETTITLECONTENTS bad in buffer");
|
"IOCTL_ES_GETTITLECONTENTS bad in buffer");
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETTITLECONTENTS bad out buffer");
|
"IOCTL_ES_GETTITLECONTENTS bad out buffer");
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
|
|
||||||
const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID);
|
||||||
|
s32 return_value = IPC_SUCCESS;
|
||||||
if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check
|
if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check
|
||||||
{
|
{
|
||||||
for (u16 i = 0; i < rNANDContent.GetNumEntries(); i++)
|
for (u16 i = 0; i < rNANDContent.GetNumEntries(); i++)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(rNANDContent.GetContentByIndex(i)->m_ContentID,
|
Memory::Write_U32(rNANDContent.GetContentByIndex(i)->m_ContentID,
|
||||||
Buffer.PayloadBuffer[0].m_Address + i * 4);
|
request.io_vectors[0].address + i * 4);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Index %d: %08x", i,
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Index %d: %08x", i,
|
||||||
rNANDContent.GetContentByIndex(i)->m_ContentID);
|
rNANDContent.GetContentByIndex(i)->m_ContentID);
|
||||||
}
|
}
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32((u32)rNANDContent.GetContentSize(), _CommandAddress + 0x4);
|
return_value = static_cast<s32>(rNANDContent.GetContentSize());
|
||||||
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Unable to open content %zu",
|
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Unable to open content %zu",
|
||||||
rNANDContent.GetContentSize());
|
rNANDContent.GetContentSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(return_value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_OPENTITLECONTENT:
|
case IOCTL_ES_OPENTITLECONTENT:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 3);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 3);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
u32 Index = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
|
u32 Index = Memory::Read_U32(request.in_vectors[2].address);
|
||||||
|
|
||||||
u32 CFD = OpenTitleContent(m_AccessIdentID++, TitleID, Index);
|
s32 CFD = OpenTitleContent(m_AccessIdentID++, TitleID, Index);
|
||||||
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, Index, CFD);
|
(u32)(TitleID >> 32), (u32)TitleID, Index, CFD);
|
||||||
|
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(CFD);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_OPENCONTENT:
|
case IOCTL_ES_OPENCONTENT:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
|
||||||
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 Index = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
|
||||||
u32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index);
|
s32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index);
|
||||||
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
||||||
|
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(CFD);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_READCONTENT:
|
case IOCTL_ES_READCONTENT:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
|
||||||
|
|
||||||
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 CFD = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
u32 Size = Buffer.PayloadBuffer[0].m_Size;
|
u32 Size = request.io_vectors[0].size;
|
||||||
u32 Addr = Buffer.PayloadBuffer[0].m_Address;
|
u32 Addr = request.io_vectors[0].address;
|
||||||
|
|
||||||
auto itr = m_ContentAccessMap.find(CFD);
|
auto itr = m_ContentAccessMap.find(CFD);
|
||||||
if (itr == m_ContentAccessMap.end())
|
if (itr == m_ContentAccessMap.end())
|
||||||
{
|
{
|
||||||
Memory::Write_U32(-1, _CommandAddress + 0x4);
|
return GetDefaultReply(-1);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
SContentAccess& rContent = itr->second;
|
SContentAccess& rContent = itr->second;
|
||||||
|
|
||||||
|
@ -573,25 +548,23 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
"IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)",
|
"IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)",
|
||||||
CFD, Addr, Size, rContent.m_Position, rContent.m_Index);
|
CFD, Addr, Size, rContent.m_Position, rContent.m_Index);
|
||||||
|
|
||||||
Memory::Write_U32(Size, _CommandAddress + 0x4);
|
return GetDefaultReply(Size);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_CLOSECONTENT:
|
case IOCTL_ES_CLOSECONTENT:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
|
||||||
|
|
||||||
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 CFD = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CLOSECONTENT: CFD %x", CFD);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CLOSECONTENT: CFD %x", CFD);
|
||||||
|
|
||||||
auto itr = m_ContentAccessMap.find(CFD);
|
auto itr = m_ContentAccessMap.find(CFD);
|
||||||
if (itr == m_ContentAccessMap.end())
|
if (itr == m_ContentAccessMap.end())
|
||||||
{
|
{
|
||||||
Memory::Write_U32(-1, _CommandAddress + 0x4);
|
return GetDefaultReply(-1);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DiscIO::CNANDContentLoader& ContentLoader = AccessContentDevice(itr->second.m_TitleID);
|
const DiscIO::CNANDContentLoader& ContentLoader = AccessContentDevice(itr->second.m_TitleID);
|
||||||
|
@ -604,25 +577,23 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
m_ContentAccessMap.erase(itr);
|
m_ContentAccessMap.erase(itr);
|
||||||
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_SEEKCONTENT:
|
case IOCTL_ES_SEEKCONTENT:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 3);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 3);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 0);
|
||||||
|
|
||||||
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 CFD = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
u32 Addr = Memory::Read_U32(request.in_vectors[1].address);
|
||||||
u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
|
u32 Mode = Memory::Read_U32(request.in_vectors[2].address);
|
||||||
|
|
||||||
auto itr = m_ContentAccessMap.find(CFD);
|
auto itr = m_ContentAccessMap.find(CFD);
|
||||||
if (itr == m_ContentAccessMap.end())
|
if (itr == m_ContentAccessMap.end())
|
||||||
{
|
{
|
||||||
Memory::Write_U32(-1, _CommandAddress + 0x4);
|
return GetDefaultReply(-1);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
SContentAccess& rContent = itr->second;
|
SContentAccess& rContent = itr->second;
|
||||||
|
|
||||||
|
@ -644,19 +615,18 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
DEBUG_LOG(WII_IPC_ES, "IOCTL_ES_SEEKCONTENT: CFD %x, Address 0x%x, Mode %i -> Pos %i", CFD,
|
DEBUG_LOG(WII_IPC_ES, "IOCTL_ES_SEEKCONTENT: CFD %x, Address 0x%x, Mode %i -> Pos %i", CFD,
|
||||||
Addr, Mode, rContent.m_Position);
|
Addr, Mode, rContent.m_Position);
|
||||||
|
|
||||||
Memory::Write_U32(rContent.m_Position, _CommandAddress + 0x4);
|
return GetDefaultReply(rContent.m_Position);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLEDIR:
|
case IOCTL_ES_GETTITLEDIR:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 1);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
|
|
||||||
char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
char* Path = (char*)Memory::GetPointer(request.io_vectors[0].address);
|
||||||
sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID);
|
sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEDIR: %s", Path);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEDIR: %s", Path);
|
||||||
|
@ -665,56 +635,55 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLEID:
|
case IOCTL_ES_GETTITLEID:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 0);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 0);
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETTITLEID no out buffer");
|
"IOCTL_ES_GETTITLEID no out buffer");
|
||||||
|
|
||||||
Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U64(m_TitleID, request.io_vectors[0].address);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_SETUID:
|
case IOCTL_ES_SETUID:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_SETUID no in buffer");
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1, "IOCTL_ES_SETUID no in buffer");
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0,
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 0,
|
||||||
"IOCTL_ES_SETUID has a payload, it shouldn't");
|
"IOCTL_ES_SETUID has a payload, it shouldn't");
|
||||||
// TODO: fs permissions based on this
|
// TODO: fs permissions based on this
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLECNT:
|
case IOCTL_ES_GETTITLECNT:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 0,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 0,
|
||||||
"IOCTL_ES_GETTITLECNT has an in buffer");
|
"IOCTL_ES_GETTITLECNT has an in buffer");
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETTITLECNT has no out buffer");
|
"IOCTL_ES_GETTITLECNT has no out buffer");
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.PayloadBuffer[0].m_Size == 4,
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors[0].size == 4,
|
||||||
"IOCTL_ES_GETTITLECNT payload[0].size != 4");
|
"IOCTL_ES_GETTITLECNT payload[0].size != 4");
|
||||||
|
|
||||||
Memory::Write_U32((u32)m_TitleIDs.size(), Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32((u32)m_TitleIDs.size(), request.io_vectors[0].address);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size());
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size());
|
||||||
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLES:
|
case IOCTL_ES_GETTITLES:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETTITLES has an in buffer");
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
"IOCTL_ES_GETTITLES has an in buffer");
|
||||||
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETTITLES has no out buffer");
|
"IOCTL_ES_GETTITLES has no out buffer");
|
||||||
|
|
||||||
u32 MaxCount = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 MaxCount = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
u32 Count = 0;
|
u32 Count = 0;
|
||||||
for (int i = 0; i < (int)m_TitleIDs.size(); i++)
|
for (int i = 0; i < (int)m_TitleIDs.size(); i++)
|
||||||
{
|
{
|
||||||
Memory::Write_U64(m_TitleIDs[i], Buffer.PayloadBuffer[0].m_Address + i * 8);
|
Memory::Write_U64(m_TitleIDs[i], request.io_vectors[0].address + i * 8);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(m_TitleIDs[i] >> 32),
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(m_TitleIDs[i] >> 32),
|
||||||
(u32)m_TitleIDs[i]);
|
(u32)m_TitleIDs[i]);
|
||||||
Count++;
|
Count++;
|
||||||
|
@ -723,18 +692,18 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: Number of titles returned %i", Count);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: Number of titles returned %i", Count);
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETVIEWCNT:
|
case IOCTL_ES_GETVIEWCNT:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETVIEWCNT no in buffer");
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
"IOCTL_ES_GETVIEWCNT no in buffer");
|
||||||
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETVIEWCNT no out buffer");
|
"IOCTL_ES_GETVIEWCNT no out buffer");
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
|
|
||||||
u32 retVal = 0;
|
u32 retVal = 0;
|
||||||
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||||
|
@ -774,20 +743,18 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWCNT for titleID: %08x/%08x (View Count = %i)",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWCNT for titleID: %08x/%08x (View Count = %i)",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, ViewCount);
|
(u32)(TitleID >> 32), (u32)TitleID, ViewCount);
|
||||||
|
|
||||||
Memory::Write_U32(ViewCount, Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(ViewCount, request.io_vectors[0].address);
|
||||||
Memory::Write_U32(retVal, _CommandAddress + 0x4);
|
return GetDefaultReply(retVal);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETVIEWS:
|
case IOCTL_ES_GETVIEWS:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "IOCTL_ES_GETVIEWS no in buffer");
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2, "IOCTL_ES_GETVIEWS no in buffer");
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETVIEWS no out buffer");
|
||||||
"IOCTL_ES_GETVIEWS no out buffer");
|
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
u32 maxViews = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
u32 maxViews = Memory::Read_U32(request.in_vectors[1].address);
|
||||||
u32 retVal = 0;
|
u32 retVal = 0;
|
||||||
|
|
||||||
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||||
|
@ -808,9 +775,9 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
pFile.ReadBytes(FileTicket, DiscIO::CNANDContentLoader::TICKET_SIZE);
|
pFile.ReadBytes(FileTicket, DiscIO::CNANDContentLoader::TICKET_SIZE);
|
||||||
++View)
|
++View)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(View, Buffer.PayloadBuffer[0].m_Address + View * 0xD8);
|
Memory::Write_U32(View, request.io_vectors[0].address + View * 0xD8);
|
||||||
Memory::CopyToEmu(Buffer.PayloadBuffer[0].m_Address + 4 + View * 0xD8,
|
Memory::CopyToEmu(request.io_vectors[0].address + 4 + View * 0xD8, FileTicket + 0x1D0,
|
||||||
FileTicket + 0x1D0, 212);
|
212);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -820,7 +787,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
// SDK or libogc, just passed to LaunchTitle, so this
|
// SDK or libogc, just passed to LaunchTitle, so this
|
||||||
// shouldn't matter at all. Just fill out some fields just
|
// shouldn't matter at all. Just fill out some fields just
|
||||||
// to be on the safe side.
|
// to be on the safe side.
|
||||||
u32 Address = Buffer.PayloadBuffer[0].m_Address;
|
u32 Address = request.io_vectors[0].address;
|
||||||
Memory::Memset(Address, 0, 0xD8);
|
Memory::Memset(Address, 0, 0xD8);
|
||||||
Memory::Write_U64(TitleID, Address + 4 + (0x1dc - 0x1d0)); // title ID
|
Memory::Write_U64(TitleID, Address + 4 + (0x1dc - 0x1d0)); // title ID
|
||||||
Memory::Write_U16(0xffff, Address + 4 + (0x1e4 - 0x1d0)); // unnnown
|
Memory::Write_U16(0xffff, Address + 4 + (0x1e4 - 0x1d0)); // unnnown
|
||||||
|
@ -840,8 +807,8 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
static_cast<u32>(Loader.GetTicket().size()) / DiscIO::CNANDContentLoader::TICKET_SIZE;
|
static_cast<u32>(Loader.GetTicket().size()) / DiscIO::CNANDContentLoader::TICKET_SIZE;
|
||||||
for (unsigned int view = 0; view != maxViews && view < view_count; ++view)
|
for (unsigned int view = 0; view != maxViews && view < view_count; ++view)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(view, Buffer.PayloadBuffer[0].m_Address + view * 0xD8);
|
Memory::Write_U32(view, request.io_vectors[0].address + view * 0xD8);
|
||||||
Memory::CopyToEmu(Buffer.PayloadBuffer[0].m_Address + 4 + view * 0xD8,
|
Memory::CopyToEmu(request.io_vectors[0].address + 4 + view * 0xD8,
|
||||||
&ticket[0x1D0 + (view * DiscIO::CNANDContentLoader::TICKET_SIZE)], 212);
|
&ticket[0x1D0 + (view * DiscIO::CNANDContentLoader::TICKET_SIZE)], 212);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -849,18 +816,18 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, maxViews);
|
(u32)(TitleID >> 32), (u32)TitleID, maxViews);
|
||||||
|
|
||||||
Memory::Write_U32(retVal, _CommandAddress + 0x4);
|
return GetDefaultReply(retVal);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETTMDVIEWCNT:
|
case IOCTL_ES_GETTMDVIEWCNT:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
"IOCTL_ES_GETTMDVIEWCNT no in buffer");
|
||||||
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
|
|
||||||
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||||
|
|
||||||
|
@ -873,24 +840,23 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
TMDViewCnt +=
|
TMDViewCnt +=
|
||||||
(u32)Loader.GetContentSize() * (4 + 2 + 2 + 8); // content id, index, type, size
|
(u32)Loader.GetContentSize() * (4 + 2 + 2 + 8); // content id, index, type, size
|
||||||
}
|
}
|
||||||
Memory::Write_U32(TMDViewCnt, Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(TMDViewCnt, request.io_vectors[0].address);
|
||||||
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt);
|
(u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt);
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETTMDVIEWS:
|
case IOCTL_ES_GETTMDVIEWS:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "IOCTL_ES_GETTMDVIEWCNT no in buffer");
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 2,
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1,
|
"IOCTL_ES_GETTMDVIEWCNT no in buffer");
|
||||||
|
_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
"IOCTL_ES_GETTMDVIEWCNT no out buffer");
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
u32 MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address);
|
||||||
|
|
||||||
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||||
|
|
||||||
|
@ -899,7 +865,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
if (Loader.IsValid())
|
if (Loader.IsValid())
|
||||||
{
|
{
|
||||||
u32 Address = Buffer.PayloadBuffer[0].m_Address;
|
u32 Address = request.io_vectors[0].address;
|
||||||
|
|
||||||
Memory::CopyToEmu(Address, Loader.GetTMDView(), DiscIO::CNANDContentLoader::TMD_VIEW_SIZE);
|
Memory::CopyToEmu(Address, Loader.GetTMDView(), DiscIO::CNANDContentLoader::TMD_VIEW_SIZE);
|
||||||
Address += DiscIO::CNANDContentLoader::TMD_VIEW_SIZE;
|
Address += DiscIO::CNANDContentLoader::TMD_VIEW_SIZE;
|
||||||
|
@ -923,62 +889,50 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
_dbg_assert_(WII_IPC_ES,
|
_dbg_assert_(WII_IPC_ES,
|
||||||
(Address - Buffer.PayloadBuffer[0].m_Address) == Buffer.PayloadBuffer[0].m_Size);
|
(Address - request.io_vectors[0].address) == request.io_vectors[0].size);
|
||||||
}
|
}
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETCONSUMPTION: // This is at least what crediar's ES module does
|
case IOCTL_ES_GETCONSUMPTION: // This is at least what crediar's ES module does
|
||||||
Memory::Write_U32(0, Buffer.PayloadBuffer[1].m_Address);
|
Memory::Write_U32(0, request.io_vectors[1].address);
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETCONSUMPTION");
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETCONSUMPTION:%d", Memory::Read_U32(_CommandAddress + 4));
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
return GetDefaultReply();
|
|
||||||
|
|
||||||
case IOCTL_ES_DELETETICKET:
|
case IOCTL_ES_DELETETICKET:
|
||||||
{
|
{
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETICKET: title: %08x/%08x", (u32)(TitleID >> 32),
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETICKET: title: %08x/%08x", (u32)(TitleID >> 32),
|
||||||
(u32)TitleID);
|
(u32)TitleID);
|
||||||
if (File::Delete(Common::GetTicketFileName(TitleID, Common::FROM_SESSION_ROOT)))
|
// Presumably return -1017 when delete fails
|
||||||
{
|
if (!File::Delete(Common::GetTicketFileName(TitleID, Common::FROM_SESSION_ROOT)))
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
}
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
else
|
|
||||||
{
|
|
||||||
// Presumably return -1017 when delete fails
|
|
||||||
Memory::Write_U32(ES_PARAMTER_SIZE_OR_ALIGNMENT, _CommandAddress + 0x4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case IOCTL_ES_DELETETITLECONTENT:
|
case IOCTL_ES_DELETETITLECONTENT:
|
||||||
{
|
{
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32),
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32),
|
||||||
(u32)TitleID);
|
(u32)TitleID);
|
||||||
if (DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT))
|
// Presumably return -1017 when title not installed TODO verify
|
||||||
{
|
if (!DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT))
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
}
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
else
|
|
||||||
{
|
|
||||||
// Presumably return -1017 when title not installed TODO verify
|
|
||||||
Memory::Write_U32(ES_PARAMTER_SIZE_OR_ALIGNMENT, _CommandAddress + 0x4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case IOCTL_ES_GETSTOREDTMDSIZE:
|
case IOCTL_ES_GETSTOREDTMDSIZE:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1,
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() == 1,
|
||||||
"IOCTL_ES_GETSTOREDTMDSIZE no in buffer");
|
"IOCTL_ES_GETSTOREDTMDSIZE no in buffer");
|
||||||
// _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_ES_GETSTOREDTMDSIZE
|
// _dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1, "IOCTL_ES_ES_GETSTOREDTMDSIZE
|
||||||
// no out buffer");
|
// no out buffer");
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||||
|
|
||||||
_dbg_assert_(WII_IPC_ES, Loader.IsValid());
|
_dbg_assert_(WII_IPC_ES, Loader.IsValid());
|
||||||
|
@ -988,40 +942,39 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
TMDCnt += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE;
|
TMDCnt += DiscIO::CNANDContentLoader::TMD_HEADER_SIZE;
|
||||||
TMDCnt += (u32)Loader.GetContentSize() * DiscIO::CNANDContentLoader::CONTENT_HEADER_SIZE;
|
TMDCnt += (u32)Loader.GetContentSize() * DiscIO::CNANDContentLoader::CONTENT_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
if (Buffer.NumberPayloadBuffer)
|
if (request.io_vectors.size())
|
||||||
Memory::Write_U32(TMDCnt, Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(TMDCnt, request.io_vectors[0].address);
|
||||||
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, TMDCnt);
|
(u32)(TitleID >> 32), (u32)TitleID, TMDCnt);
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IOCTL_ES_GETSTOREDTMD:
|
case IOCTL_ES_GETSTOREDTMD:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer > 0, "IOCTL_ES_GETSTOREDTMD no in buffer");
|
_dbg_assert_msg_(WII_IPC_ES, request.in_vectors.size() > 0,
|
||||||
|
"IOCTL_ES_GETSTOREDTMD no in buffer");
|
||||||
// requires 1 inbuffer and no outbuffer, presumably outbuffer required when second inbuffer is
|
// requires 1 inbuffer and no outbuffer, presumably outbuffer required when second inbuffer is
|
||||||
// used for maxcount (allocated mem?)
|
// used for maxcount (allocated mem?)
|
||||||
// called with 1 inbuffer after deleting a titleid
|
// called with 1 inbuffer after deleting a titleid
|
||||||
//_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETSTOREDTMD no out
|
//_dbg_assert_msg_(WII_IPC_ES, request.io_vectors.size() == 1, "IOCTL_ES_GETSTOREDTMD no out
|
||||||
// buffer");
|
// buffer");
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
u32 MaxCount = 0;
|
u32 MaxCount = 0;
|
||||||
if (Buffer.NumberInBuffer > 1)
|
if (request.in_vectors.size() > 1)
|
||||||
{
|
{
|
||||||
// TODO: actually use this param in when writing to the outbuffer :/
|
// TODO: actually use this param in when writing to the outbuffer :/
|
||||||
MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
MaxCount = Memory::Read_U32(request.in_vectors[1].address);
|
||||||
}
|
}
|
||||||
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
const DiscIO::CNANDContentLoader& Loader = AccessContentDevice(TitleID);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffer size: %i",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffer size: %i",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
||||||
|
|
||||||
if (Loader.IsValid() && Buffer.NumberPayloadBuffer)
|
if (Loader.IsValid() && request.io_vectors.size())
|
||||||
{
|
{
|
||||||
u32 Address = Buffer.PayloadBuffer[0].m_Address;
|
u32 Address = request.io_vectors[0].address;
|
||||||
|
|
||||||
Memory::CopyToEmu(Address, Loader.GetTMDHeader(),
|
Memory::CopyToEmu(Address, Loader.GetTMDHeader(),
|
||||||
DiscIO::CNANDContentLoader::TMD_HEADER_SIZE);
|
DiscIO::CNANDContentLoader::TMD_HEADER_SIZE);
|
||||||
|
@ -1036,24 +989,23 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
_dbg_assert_(WII_IPC_ES,
|
_dbg_assert_(WII_IPC_ES,
|
||||||
(Address - Buffer.PayloadBuffer[0].m_Address) == Buffer.PayloadBuffer[0].m_Size);
|
(Address - request.io_vectors[0].address) == request.io_vectors[0].size);
|
||||||
}
|
}
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x (buffer size: %i)",
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x (buffer size: %i)",
|
||||||
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
(u32)(TitleID >> 32), (u32)TitleID, MaxCount);
|
||||||
return GetDefaultReply();
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_ENCRYPT:
|
case IOCTL_ES_ENCRYPT:
|
||||||
{
|
{
|
||||||
u32 keyIndex = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
u8* IV = Memory::GetPointer(Buffer.InBuffer[1].m_Address);
|
u8* IV = Memory::GetPointer(request.in_vectors[1].address);
|
||||||
u8* source = Memory::GetPointer(Buffer.InBuffer[2].m_Address);
|
u8* source = Memory::GetPointer(request.in_vectors[2].address);
|
||||||
u32 size = Buffer.InBuffer[2].m_Size;
|
u32 size = request.in_vectors[2].size;
|
||||||
u8* newIV = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
u8* newIV = Memory::GetPointer(request.io_vectors[0].address);
|
||||||
u8* destination = Memory::GetPointer(Buffer.PayloadBuffer[1].m_Address);
|
u8* destination = Memory::GetPointer(request.io_vectors[1].address);
|
||||||
|
|
||||||
mbedtls_aes_context AES_ctx;
|
mbedtls_aes_context AES_ctx;
|
||||||
mbedtls_aes_setkey_enc(&AES_ctx, keyTable[keyIndex], 128);
|
mbedtls_aes_setkey_enc(&AES_ctx, keyTable[keyIndex], 128);
|
||||||
|
@ -1067,12 +1019,12 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_ES_DECRYPT:
|
case IOCTL_ES_DECRYPT:
|
||||||
{
|
{
|
||||||
u32 keyIndex = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
u8* IV = Memory::GetPointer(Buffer.InBuffer[1].m_Address);
|
u8* IV = Memory::GetPointer(request.in_vectors[1].address);
|
||||||
u8* source = Memory::GetPointer(Buffer.InBuffer[2].m_Address);
|
u8* source = Memory::GetPointer(request.in_vectors[2].address);
|
||||||
u32 size = Buffer.InBuffer[2].m_Size;
|
u32 size = request.in_vectors[2].size;
|
||||||
u8* newIV = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
u8* newIV = Memory::GetPointer(request.io_vectors[0].address);
|
||||||
u8* destination = Memory::GetPointer(Buffer.PayloadBuffer[1].m_Address);
|
u8* destination = Memory::GetPointer(request.io_vectors[1].address);
|
||||||
|
|
||||||
DecryptContent(keyIndex, IV, source, size, newIV, destination);
|
DecryptContent(keyIndex, IV, source, size, newIV, destination);
|
||||||
|
|
||||||
|
@ -1083,17 +1035,17 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_ES_LAUNCH:
|
case IOCTL_ES_LAUNCH:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 2);
|
_dbg_assert_(WII_IPC_ES, request.in_vectors.size() == 2);
|
||||||
bool bSuccess = false;
|
bool bSuccess = false;
|
||||||
bool bReset = false;
|
bool bReset = false;
|
||||||
u16 IOSv = 0xffff;
|
u16 IOSv = 0xffff;
|
||||||
|
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
|
||||||
u32 view = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
u32 view = Memory::Read_U32(request.in_vectors[1].address);
|
||||||
u64 ticketid = Memory::Read_U64(Buffer.InBuffer[1].m_Address + 4);
|
u64 ticketid = Memory::Read_U64(request.in_vectors[1].address + 4);
|
||||||
u32 devicetype = Memory::Read_U32(Buffer.InBuffer[1].m_Address + 12);
|
u32 devicetype = Memory::Read_U32(request.in_vectors[1].address + 12);
|
||||||
u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address + 16);
|
u64 titleid = Memory::Read_U64(request.in_vectors[1].address + 16);
|
||||||
u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address + 24);
|
u16 access = Memory::Read_U16(request.in_vectors[1].address + 24);
|
||||||
|
|
||||||
// ES_LAUNCH should probably reset thw whole state, which at least means closing all open files.
|
// ES_LAUNCH should probably reset thw whole state, which at least means closing all open files.
|
||||||
// leaving them open through ES_LAUNCH may cause hangs and other funky behavior
|
// leaving them open through ES_LAUNCH may cause hangs and other funky behavior
|
||||||
|
@ -1194,13 +1146,8 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
Memory::Write_U16(0xFFFF, 0x00003142);
|
Memory::Write_U16(0xFFFF, 0x00003142);
|
||||||
Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188);
|
Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188);
|
||||||
|
|
||||||
// TODO: provide correct return code when bSuccess= false
|
|
||||||
// Note: If we just reset the PPC, don't write anything to the command buffer. This
|
// Note: If we just reset the PPC, don't write anything to the command buffer. This
|
||||||
// could clobber the DOL we just loaded.
|
// could clobber the DOL we just loaded.
|
||||||
if (!bReset)
|
|
||||||
{
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERROR_LOG(WII_IPC_ES,
|
ERROR_LOG(WII_IPC_ES,
|
||||||
"IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x",
|
"IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x",
|
||||||
|
@ -1213,14 +1160,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
if (!bReset)
|
if (!bReset)
|
||||||
{
|
{
|
||||||
// The command type is overwritten with the reply type.
|
// The command type is overwritten with the reply type.
|
||||||
Memory::Write_U32(IPC_REPLY, _CommandAddress);
|
Memory::Write_U32(IPC_REPLY, request.address);
|
||||||
// IOS also writes back the command that was responded to in the FD field.
|
// IOS also writes back the command that was responded to in the FD field.
|
||||||
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8);
|
Memory::Write_U32(IPC_CMD_IOCTLV, request.address + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
|
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
|
||||||
// involves restarting IOS; IOS generates two acknowledgements in a row.
|
// involves restarting IOS; IOS generates two acknowledgements in a row.
|
||||||
WII_IPC_HLE_Interface::EnqueueCommandAcknowledgement(_CommandAddress, 0);
|
WII_IPC_HLE_Interface::EnqueueCommandAcknowledgement(request.address, 0);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1231,14 +1178,13 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
// -1017
|
// -1017
|
||||||
// if the IOS didn't find the Korean keys and 0 if it does. 0 leads to a error 003
|
// if the IOS didn't find the Korean keys and 0 if it does. 0 leads to a error 003
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
|
||||||
Memory::Write_U32(ES_PARAMTER_SIZE_OR_ALIGNMENT, _CommandAddress + 0x4);
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
return GetDefaultReply();
|
|
||||||
|
|
||||||
case IOCTL_ES_GETDEVICECERT: // (Input: none, Output: 384 bytes)
|
case IOCTL_ES_GETDEVICECERT: // (Input: none, Output: 384 bytes)
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICECERT");
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICECERT");
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, request.io_vectors.size() == 1);
|
||||||
u8* destination = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
u8* destination = Memory::GetPointer(request.io_vectors[0].address);
|
||||||
|
|
||||||
EcWii& ec = EcWii::GetInstance();
|
EcWii& ec = EcWii::GetInstance();
|
||||||
get_ng_cert(destination, ec.getNgId(), ec.getNgKeyId(), ec.getNgPriv(), ec.getNgSig());
|
get_ng_cert(destination, ec.getNgId(), ec.getNgKeyId(), ec.getNgPriv(), ec.getNgSig());
|
||||||
|
@ -1248,10 +1194,10 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
case IOCTL_ES_SIGN:
|
case IOCTL_ES_SIGN:
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SIGN");
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SIGN");
|
||||||
u8* ap_cert_out = Memory::GetPointer(Buffer.PayloadBuffer[1].m_Address);
|
u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
|
||||||
u8* data = Memory::GetPointer(Buffer.InBuffer[0].m_Address);
|
u8* data = Memory::GetPointer(request.in_vectors[0].address);
|
||||||
u32 data_size = Buffer.InBuffer[0].m_Size;
|
u32 data_size = request.in_vectors[0].size;
|
||||||
u8* sig_out = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
|
||||||
|
|
||||||
EcWii& ec = EcWii::GetInstance();
|
EcWii& ec = EcWii::GetInstance();
|
||||||
get_ap_sig_and_cert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.getNgPriv(),
|
get_ap_sig_and_cert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.getNgPriv(),
|
||||||
|
@ -1264,7 +1210,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETBOOT2VERSION");
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETBOOT2VERSION");
|
||||||
|
|
||||||
Memory::Write_U32(
|
Memory::Write_U32(
|
||||||
4, Buffer.PayloadBuffer[0].m_Address); // as of 26/02/2012, this was latest bootmii version
|
4, request.io_vectors[0].address); // as of 26/02/2012, this was latest bootmii version
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1277,20 +1223,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_ES_GETOWNEDTITLECNT:
|
case IOCTL_ES_GETOWNEDTITLECNT:
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETOWNEDTITLECNT");
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETOWNEDTITLECNT");
|
||||||
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(0, request.io_vectors[0].address);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
INFO_LOG(WII_IPC_ES, "CWII_IPC_HLE_Device_es: 0x%x", Buffer.Parameter);
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_HLE);
|
||||||
DumpCommands(_CommandAddress, 8, LogTypes::WII_IPC_ES);
|
|
||||||
INFO_LOG(WII_IPC_ES, "command.Parameter: 0x%08x", Buffer.Parameter);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write return value (0 means OK)
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DiscIO::CNANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 title_id)
|
const DiscIO::CNANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 title_id)
|
||||||
|
|
|
@ -27,8 +27,6 @@ class CWII_IPC_HLE_Device_es : public IWII_IPC_HLE_Device
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName);
|
CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName);
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_es();
|
|
||||||
|
|
||||||
void LoadWAD(const std::string& _rContentFile);
|
void LoadWAD(const std::string& _rContentFile);
|
||||||
|
|
||||||
// Internal implementation of the ES_DECRYPT ioctlv.
|
// Internal implementation of the ES_DECRYPT ioctlv.
|
||||||
|
@ -38,10 +36,9 @@ public:
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
|
void Close() override;
|
||||||
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
|
||||||
|
|
||||||
static u32 ES_DIVerify(const std::vector<u8>& tmd);
|
static u32 ES_DIVerify(const std::vector<u8>& tmd);
|
||||||
|
|
||||||
|
@ -116,7 +113,7 @@ private:
|
||||||
ES_INVALID_TMD = -106, // or access denied
|
ES_INVALID_TMD = -106, // or access denied
|
||||||
ES_READ_LESS_DATA_THAN_EXPECTED = -1009,
|
ES_READ_LESS_DATA_THAN_EXPECTED = -1009,
|
||||||
ES_WRITE_FAILURE = -1010,
|
ES_WRITE_FAILURE = -1010,
|
||||||
ES_PARAMTER_SIZE_OR_ALIGNMENT = -1017,
|
ES_PARAMETER_SIZE_OR_ALIGNMENT = -1017,
|
||||||
ES_HASH_DOESNT_MATCH = -1022,
|
ES_HASH_DOESNT_MATCH = -1022,
|
||||||
ES_MEM_ALLOC_FAILED = -1024,
|
ES_MEM_ALLOC_FAILED = -1024,
|
||||||
ES_INCORRECT_ACCESS_RIGHT = -1026,
|
ES_INCORRECT_ACCESS_RIGHT = -1026,
|
||||||
|
|
|
@ -32,18 +32,14 @@ CWII_IPC_HLE_Device_fs::CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string&
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_fs::~CWII_IPC_HLE_Device_fs()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~1/1000th of a second is too short and causes hangs in Wii Party
|
// ~1/1000th of a second is too short and causes hangs in Wii Party
|
||||||
// Play it safe at 1/500th
|
// Play it safe at 1/500th
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_fs::GetFSReply() const
|
IPCCommandResult CWII_IPC_HLE_Device_fs::GetFSReply(const s32 return_value) const
|
||||||
{
|
{
|
||||||
return {true, SystemTimers::GetTicksPerSecond() / 500};
|
return {return_value, true, SystemTimers::GetTicksPerSecond() / 500};
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_fs::Open(u32 _CommandAddress, u32 _Mode)
|
IOSReturnCode CWII_IPC_HLE_Device_fs::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
// clear tmp folder
|
// clear tmp folder
|
||||||
{
|
{
|
||||||
|
@ -53,7 +49,7 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::Open(u32 _CommandAddress, u32 _Mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetFSReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get total filesize of contents of a directory (recursive)
|
// Get total filesize of contents of a directory (recursive)
|
||||||
|
@ -71,27 +67,20 @@ static u64 ComputeTotalFileSize(const File::FSTEntry& parentEntry)
|
||||||
return sizeOfFiles;
|
return sizeOfFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
u32 ReturnValue = IPC_SUCCESS;
|
s32 return_value = IPC_SUCCESS;
|
||||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
switch (request.request)
|
||||||
|
|
||||||
// Prepare the out buffer(s) with zeros as a safety precaution
|
|
||||||
// to avoid returning bad values
|
|
||||||
for (const auto& buffer : CommandBuffer.PayloadBuffer)
|
|
||||||
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
|
|
||||||
|
|
||||||
switch (CommandBuffer.Parameter)
|
|
||||||
{
|
{
|
||||||
case IOCTLV_READ_DIR:
|
case IOCTLV_READ_DIR:
|
||||||
{
|
{
|
||||||
const std::string relative_path =
|
const std::string relative_path =
|
||||||
Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size);
|
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
|
|
||||||
if (!IsValidWiiPath(relative_path))
|
if (!IsValidWiiPath(relative_path))
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relative_path.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relative_path.c_str());
|
||||||
ReturnValue = FS_EINVAL;
|
return_value = FS_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +92,7 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
||||||
if (!File::Exists(DirName))
|
if (!File::Exists(DirName))
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str());
|
||||||
ReturnValue = FS_ENOENT;
|
return_value = FS_ENOENT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (!File::IsDirectory(DirName))
|
else if (!File::IsDirectory(DirName))
|
||||||
|
@ -112,19 +101,19 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
||||||
// Games don't usually seem to care WHICH error they get, as long as it's <
|
// Games don't usually seem to care WHICH error they get, as long as it's <
|
||||||
// Well the system menu CARES!
|
// Well the system menu CARES!
|
||||||
WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_EINVAL");
|
WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_EINVAL");
|
||||||
ReturnValue = FS_EINVAL;
|
return_value = FS_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
File::FSTEntry entry = File::ScanDirectoryTree(DirName, false);
|
File::FSTEntry entry = File::ScanDirectoryTree(DirName, false);
|
||||||
|
|
||||||
// it is one
|
// it is one
|
||||||
if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1))
|
if ((request.in_vectors.size() == 1) && (request.io_vectors.size() == 1))
|
||||||
{
|
{
|
||||||
size_t numFile = entry.children.size();
|
size_t numFile = entry.children.size();
|
||||||
INFO_LOG(WII_IPC_FILEIO, "\t%zu files found", numFile);
|
INFO_LOG(WII_IPC_FILEIO, "\t%zu files found", numFile);
|
||||||
|
|
||||||
Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32((u32)numFile, request.io_vectors[0].address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -140,13 +129,12 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
||||||
return one.virtualName < two.virtualName;
|
return one.virtualName < two.virtualName;
|
||||||
});
|
});
|
||||||
|
|
||||||
u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address);
|
u32 MaxEntries = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
|
||||||
memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0,
|
memset(Memory::GetPointer(request.io_vectors[0].address), 0, request.io_vectors[0].size);
|
||||||
CommandBuffer.PayloadBuffer[0].m_Size);
|
|
||||||
|
|
||||||
size_t numFiles = 0;
|
size_t numFiles = 0;
|
||||||
char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address));
|
char* pFilename = (char*)Memory::GetPointer((u32)(request.io_vectors[0].address));
|
||||||
|
|
||||||
for (size_t i = 0; i < entry.children.size() && i < MaxEntries; i++)
|
for (size_t i = 0; i < entry.children.size() && i < MaxEntries; i++)
|
||||||
{
|
{
|
||||||
|
@ -160,29 +148,29 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str());
|
INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32((u32)numFiles, CommandBuffer.PayloadBuffer[1].m_Address);
|
Memory::Write_U32((u32)numFiles, request.io_vectors[1].address);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue = IPC_SUCCESS;
|
return_value = IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTLV_GETUSAGE:
|
case IOCTLV_GETUSAGE:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer.size() == 2);
|
_dbg_assert_(WII_IPC_FILEIO, request.io_vectors.size() == 2);
|
||||||
_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[0].m_Size == 4);
|
_dbg_assert_(WII_IPC_FILEIO, request.io_vectors[0].size == 4);
|
||||||
_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[1].m_Size == 4);
|
_dbg_assert_(WII_IPC_FILEIO, request.io_vectors[1].size == 4);
|
||||||
|
|
||||||
// this command sucks because it asks of the number of used
|
// this command sucks because it asks of the number of used
|
||||||
// fsBlocks and inodes
|
// fsBlocks and inodes
|
||||||
// It should be correct, but don't count on it...
|
// It should be correct, but don't count on it...
|
||||||
std::string relativepath =
|
std::string relativepath =
|
||||||
Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size);
|
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
|
|
||||||
if (!IsValidWiiPath(relativepath))
|
if (!IsValidWiiPath(relativepath))
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relativepath.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relativepath.c_str());
|
||||||
ReturnValue = FS_EINVAL;
|
return_value = FS_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +202,7 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
fsBlocks = (u32)(totalSize / (16 * 1024)); // one bock is 16kb
|
fsBlocks = (u32)(totalSize / (16 * 1024)); // one bock is 16kb
|
||||||
}
|
}
|
||||||
ReturnValue = IPC_SUCCESS;
|
return_value = IPC_SUCCESS;
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes);
|
INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes);
|
||||||
}
|
}
|
||||||
|
@ -222,54 +210,37 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
fsBlocks = 0;
|
fsBlocks = 0;
|
||||||
iNodes = 0;
|
iNodes = 0;
|
||||||
ReturnValue = IPC_SUCCESS;
|
return_value = IPC_SUCCESS;
|
||||||
WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address);
|
Memory::Write_U32(fsBlocks, request.io_vectors[0].address);
|
||||||
Memory::Write_U32(iNodes, CommandBuffer.PayloadBuffer[1].m_Address);
|
Memory::Write_U32(iNodes, request.io_vectors[1].address);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PanicAlert("CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter);
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_FILEIO);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
|
return GetFSReply(return_value);
|
||||||
|
|
||||||
return GetFSReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtl(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
// u32 DeviceID = Memory::Read_U32(_CommandAddress + 8);
|
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
|
||||||
|
const s32 return_value = ExecuteCommand(request);
|
||||||
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
|
return GetFSReply(return_value);
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
|
||||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
|
||||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
|
||||||
|
|
||||||
/* Prepare the out buffer(s) with zeroes as a safety precaution
|
|
||||||
to avoid returning bad values. */
|
|
||||||
// LOG(WII_IPC_FILEIO, "Cleared %u bytes of the out buffer", _BufferOutSize);
|
|
||||||
Memory::Memset(BufferOut, 0, BufferOutSize);
|
|
||||||
|
|
||||||
u32 ReturnValue = ExecuteCommand(Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
|
|
||||||
|
|
||||||
return GetFSReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize,
|
s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(const IOSIOCtlRequest& request)
|
||||||
u32 _BufferOut, u32 _BufferOutSize)
|
|
||||||
{
|
{
|
||||||
switch (_Parameter)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
case IOCTL_GET_STATS:
|
case IOCTL_GET_STATS:
|
||||||
{
|
{
|
||||||
if (_BufferOutSize < 0x1c)
|
if (request.buffer_out_size < 0x1c)
|
||||||
return -1017;
|
return -1017;
|
||||||
|
|
||||||
WARN_LOG(WII_IPC_FILEIO, "FS: GET STATS - returning static values for now");
|
WARN_LOG(WII_IPC_FILEIO, "FS: GET STATS - returning static values for now");
|
||||||
|
@ -285,7 +256,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
fs.Free_INodes = 0x146B;
|
fs.Free_INodes = 0x146B;
|
||||||
fs.Used_Inodes = 0x0394;
|
fs.Used_Inodes = 0x0394;
|
||||||
|
|
||||||
std::memcpy(Memory::GetPointer(_BufferOut), &fs, sizeof(NANDStat));
|
std::memcpy(Memory::GetPointer(request.buffer_out), &fs, sizeof(NANDStat));
|
||||||
|
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -293,8 +264,8 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
|
|
||||||
case IOCTL_CREATE_DIR:
|
case IOCTL_CREATE_DIR:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
|
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
|
||||||
u32 Addr = _BufferIn;
|
u32 Addr = request.buffer_in;
|
||||||
|
|
||||||
u32 OwnerID = Memory::Read_U32(Addr);
|
u32 OwnerID = Memory::Read_U32(Addr);
|
||||||
Addr += 4;
|
Addr += 4;
|
||||||
|
@ -325,7 +296,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
|
|
||||||
case IOCTL_SET_ATTR:
|
case IOCTL_SET_ATTR:
|
||||||
{
|
{
|
||||||
u32 Addr = _BufferIn;
|
u32 Addr = request.buffer_in;
|
||||||
|
|
||||||
u32 OwnerID = Memory::Read_U32(Addr);
|
u32 OwnerID = Memory::Read_U32(Addr);
|
||||||
Addr += 4;
|
Addr += 4;
|
||||||
|
@ -362,14 +333,14 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
|
|
||||||
case IOCTL_GET_ATTR:
|
case IOCTL_GET_ATTR:
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_FILEIO, _BufferOutSize == 76,
|
_dbg_assert_msg_(WII_IPC_FILEIO, request.buffer_out_size == 76,
|
||||||
" GET_ATTR needs an 76 bytes large output buffer but it is %i bytes large",
|
" GET_ATTR needs an 76 bytes large output buffer but it is %i bytes large",
|
||||||
_BufferOutSize);
|
request.buffer_out_size);
|
||||||
|
|
||||||
u32 OwnerID = 0;
|
u32 OwnerID = 0;
|
||||||
u16 GroupID = 0x3031; // this is also known as makercd, 01 (0x3031) for nintendo and 08
|
u16 GroupID = 0x3031; // this is also known as makercd, 01 (0x3031) for nintendo and 08
|
||||||
// (0x3038) for MH3 etc
|
// (0x3038) for MH3 etc
|
||||||
const std::string wii_path = Memory::GetString(_BufferIn, 64);
|
const std::string wii_path = Memory::GetString(request.buffer_in, 64);
|
||||||
if (!IsValidWiiPath(wii_path))
|
if (!IsValidWiiPath(wii_path))
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
|
||||||
|
@ -400,14 +371,14 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
}
|
}
|
||||||
|
|
||||||
// write answer to buffer
|
// write answer to buffer
|
||||||
if (_BufferOutSize == 76)
|
if (request.buffer_out_size == 76)
|
||||||
{
|
{
|
||||||
u32 Addr = _BufferOut;
|
u32 Addr = request.buffer_out;
|
||||||
Memory::Write_U32(OwnerID, Addr);
|
Memory::Write_U32(OwnerID, Addr);
|
||||||
Addr += 4;
|
Addr += 4;
|
||||||
Memory::Write_U16(GroupID, Addr);
|
Memory::Write_U16(GroupID, Addr);
|
||||||
Addr += 2;
|
Addr += 2;
|
||||||
memcpy(Memory::GetPointer(Addr), Memory::GetPointer(_BufferIn), 64);
|
memcpy(Memory::GetPointer(Addr), Memory::GetPointer(request.buffer_in), 64);
|
||||||
Addr += 64;
|
Addr += 64;
|
||||||
Memory::Write_U8(OwnerPerm, Addr);
|
Memory::Write_U8(OwnerPerm, Addr);
|
||||||
Addr += 1;
|
Addr += 1;
|
||||||
|
@ -425,10 +396,10 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
|
|
||||||
case IOCTL_DELETE_FILE:
|
case IOCTL_DELETE_FILE:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
|
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
|
||||||
int Offset = 0;
|
int Offset = 0;
|
||||||
|
|
||||||
const std::string wii_path = Memory::GetString(_BufferIn + Offset, 64);
|
const std::string wii_path = Memory::GetString(request.buffer_in + Offset, 64);
|
||||||
if (!IsValidWiiPath(wii_path))
|
if (!IsValidWiiPath(wii_path))
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
|
||||||
|
@ -455,10 +426,10 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
|
|
||||||
case IOCTL_RENAME_FILE:
|
case IOCTL_RENAME_FILE:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
|
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
|
||||||
int Offset = 0;
|
int Offset = 0;
|
||||||
|
|
||||||
const std::string wii_path = Memory::GetString(_BufferIn + Offset, 64);
|
const std::string wii_path = Memory::GetString(request.buffer_in + Offset, 64);
|
||||||
if (!IsValidWiiPath(wii_path))
|
if (!IsValidWiiPath(wii_path))
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
|
||||||
|
@ -467,7 +438,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
std::string Filename = HLE_IPC_BuildFilename(wii_path);
|
std::string Filename = HLE_IPC_BuildFilename(wii_path);
|
||||||
Offset += 64;
|
Offset += 64;
|
||||||
|
|
||||||
const std::string wii_path_rename = Memory::GetString(_BufferIn + Offset, 64);
|
const std::string wii_path_rename = Memory::GetString(request.buffer_in + Offset, 64);
|
||||||
if (!IsValidWiiPath(wii_path_rename))
|
if (!IsValidWiiPath(wii_path_rename))
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path_rename.c_str());
|
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path_rename.c_str());
|
||||||
|
@ -503,9 +474,9 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
|
|
||||||
case IOCTL_CREATE_FILE:
|
case IOCTL_CREATE_FILE:
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
|
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
|
||||||
|
|
||||||
u32 Addr = _BufferIn;
|
u32 Addr = request.buffer_in;
|
||||||
u32 OwnerID = Memory::Read_U32(Addr);
|
u32 OwnerID = Memory::Read_U32(Addr);
|
||||||
Addr += 4;
|
Addr += 4;
|
||||||
u16 GroupID = Memory::Read_U16(Addr);
|
u16 GroupID = Memory::Read_U16(Addr);
|
||||||
|
@ -563,9 +534,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_FILEIO, "CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter);
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_FILEIO);
|
||||||
PanicAlert("CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FS_EINVAL;
|
return FS_EINVAL;
|
||||||
|
|
|
@ -27,14 +27,12 @@ class CWII_IPC_HLE_Device_fs : public IWII_IPC_HLE_Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string& _rDeviceName);
|
CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string& _rDeviceName);
|
||||||
virtual ~CWII_IPC_HLE_Device_fs();
|
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
|
@ -51,7 +49,6 @@ private:
|
||||||
IOCTL_SHUTDOWN = 0x0D
|
IOCTL_SHUTDOWN = 0x0D
|
||||||
};
|
};
|
||||||
|
|
||||||
IPCCommandResult GetFSReply() const;
|
IPCCommandResult GetFSReply(s32 return_value) const;
|
||||||
s32 ExecuteCommand(u32 Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut,
|
s32 ExecuteCommand(const IOSIOCtlRequest& request);
|
||||||
u32 _BufferOutSize);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,12 +37,9 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
|
||||||
std::lock_guard<std::mutex> lk(hid->m_device_list_reply_mutex);
|
std::lock_guard<std::mutex> lk(hid->m_device_list_reply_mutex);
|
||||||
if (hid->deviceCommandAddress != 0)
|
if (hid->deviceCommandAddress != 0)
|
||||||
{
|
{
|
||||||
hid->FillOutDevices(Memory::Read_U32(hid->deviceCommandAddress + 0x18),
|
IOSIOCtlRequest request{hid->deviceCommandAddress};
|
||||||
Memory::Read_U32(hid->deviceCommandAddress + 0x1C));
|
hid->FillOutDevices(request);
|
||||||
|
WII_IPC_HLE_Interface::EnqueueReply(request, IPC_SUCCESS, 0,
|
||||||
// Return value
|
|
||||||
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(hid->deviceCommandAddress, 0,
|
|
||||||
CoreTiming::FromThread::NON_CPU);
|
CoreTiming::FromThread::NON_CPU);
|
||||||
hid->deviceCommandAddress = 0;
|
hid->deviceCommandAddress = 0;
|
||||||
}
|
}
|
||||||
|
@ -56,16 +53,15 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer* transfer)
|
void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer* transfer)
|
||||||
{
|
{
|
||||||
int ret = IPC_EINVAL;
|
s32 ret = IPC_EINVAL;
|
||||||
u32 replyAddress = (u32)(size_t)transfer->user_data;
|
u32 replyAddress = (u32)(size_t)transfer->user_data;
|
||||||
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
|
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
|
||||||
{
|
{
|
||||||
ret = transfer->length;
|
ret = transfer->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return value
|
IOSIOCtlRequest request{replyAddress};
|
||||||
Memory::Write_U32(ret, replyAddress + 4);
|
WII_IPC_HLE_Interface::EnqueueReply(request, ret, 0, CoreTiming::FromThread::NON_CPU);
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(replyAddress, 0, CoreTiming::FromThread::NON_CPU);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_hid::CWII_IPC_HLE_Device_hid(u32 _DeviceID, const std::string& _rDeviceName)
|
CWII_IPC_HLE_Device_hid::CWII_IPC_HLE_Device_hid(u32 _DeviceID, const std::string& _rDeviceName)
|
||||||
|
@ -105,53 +101,36 @@ CWII_IPC_HLE_Device_hid::~CWII_IPC_HLE_Device_hid()
|
||||||
libusb_exit(nullptr);
|
libusb_exit(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
if (Core::g_want_determinism)
|
if (Core::g_want_determinism)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(-1, _CommandAddress + 0x4);
|
return GetDefaultReply(IPC_EACCES);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
|
s32 return_value = IPC_SUCCESS;
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
switch (request.request)
|
||||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
|
||||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
|
||||||
|
|
||||||
u32 ReturnValue = 0;
|
|
||||||
switch (Parameter)
|
|
||||||
{
|
{
|
||||||
case IOCTL_HID_GET_ATTACHED:
|
case IOCTL_HID_GET_ATTACHED:
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
deviceCommandAddress = request.address;
|
||||||
BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
deviceCommandAddress = _CommandAddress;
|
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
case IOCTL_HID_OPEN:
|
case IOCTL_HID_OPEN:
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Open) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn,
|
|
||||||
BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
|
|
||||||
// hid version, apparently
|
// hid version, apparently
|
||||||
ReturnValue = 0x40001;
|
return_value = 0x40001;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_HID_SET_SUSPEND:
|
case IOCTL_HID_SET_SUSPEND:
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Set Suspend) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
|
||||||
BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
// not actually implemented in IOS
|
// not actually implemented in IOS
|
||||||
ReturnValue = 0;
|
return_value = IPC_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_HID_CANCEL_INTERRUPT:
|
case IOCTL_HID_CANCEL_INTERRUPT:
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_HID,
|
return_value = IPC_SUCCESS;
|
||||||
"HID::IOCtl(Cancel Interrupt) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn,
|
|
||||||
BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
ReturnValue = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_HID_CONTROL:
|
case IOCTL_HID_CONTROL:
|
||||||
|
@ -161,15 +140,15 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
||||||
-4 Can't find device specified
|
-4 Can't find device specified
|
||||||
*/
|
*/
|
||||||
|
|
||||||
u32 dev_num = Memory::Read_U32(BufferIn + 0x10);
|
u32 dev_num = Memory::Read_U32(request.buffer_in + 0x10);
|
||||||
u8 bmRequestType = Memory::Read_U8(BufferIn + 0x14);
|
u8 bmRequestType = Memory::Read_U8(request.buffer_in + 0x14);
|
||||||
u8 bRequest = Memory::Read_U8(BufferIn + 0x15);
|
u8 bRequest = Memory::Read_U8(request.buffer_in + 0x15);
|
||||||
u16 wValue = Memory::Read_U16(BufferIn + 0x16);
|
u16 wValue = Memory::Read_U16(request.buffer_in + 0x16);
|
||||||
u16 wIndex = Memory::Read_U16(BufferIn + 0x18);
|
u16 wIndex = Memory::Read_U16(request.buffer_in + 0x18);
|
||||||
u16 wLength = Memory::Read_U16(BufferIn + 0x1A);
|
u16 wLength = Memory::Read_U16(request.buffer_in + 0x1A);
|
||||||
u32 data = Memory::Read_U32(BufferIn + 0x1C);
|
u32 data = Memory::Read_U32(request.buffer_in + 0x1C);
|
||||||
|
|
||||||
ReturnValue = IPC_EINVAL;
|
return_value = IPC_EINVAL;
|
||||||
|
|
||||||
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
|
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
|
||||||
|
|
||||||
|
@ -185,12 +164,14 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
||||||
libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength);
|
libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength);
|
||||||
Memory::CopyFromEmu(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
|
Memory::CopyFromEmu(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
|
||||||
libusb_fill_control_transfer(transfer, dev_handle, buffer, handleUsbUpdates,
|
libusb_fill_control_transfer(transfer, dev_handle, buffer, handleUsbUpdates,
|
||||||
(void*)(size_t)_CommandAddress, /* no timeout */ 0);
|
(void*)(size_t)request.address, /* no timeout */ 0);
|
||||||
libusb_submit_transfer(transfer);
|
libusb_submit_transfer(transfer);
|
||||||
|
|
||||||
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i), BufferOut:
|
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i),
|
||||||
|
// request.buffer_out:
|
||||||
// (%08x, %i)",
|
// (%08x, %i)",
|
||||||
// bmRequestType, bRequest, BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
// bmRequestType, bRequest, BufferIn, request.buffer_in_size, request.buffer_out,
|
||||||
|
// request.buffer_out_size);
|
||||||
|
|
||||||
// It's the async way!
|
// It's the async way!
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
|
@ -198,13 +179,13 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
||||||
case IOCTL_HID_INTERRUPT_OUT:
|
case IOCTL_HID_INTERRUPT_OUT:
|
||||||
case IOCTL_HID_INTERRUPT_IN:
|
case IOCTL_HID_INTERRUPT_IN:
|
||||||
{
|
{
|
||||||
u32 dev_num = Memory::Read_U32(BufferIn + 0x10);
|
u32 dev_num = Memory::Read_U32(request.buffer_in + 0x10);
|
||||||
u32 endpoint = Memory::Read_U32(BufferIn + 0x14);
|
u32 endpoint = Memory::Read_U32(request.buffer_in + 0x14);
|
||||||
u32 length = Memory::Read_U32(BufferIn + 0x18);
|
u32 length = Memory::Read_U32(request.buffer_in + 0x18);
|
||||||
|
|
||||||
u32 data = Memory::Read_U32(BufferIn + 0x1C);
|
u32 data = Memory::Read_U32(request.buffer_in + 0x1C);
|
||||||
|
|
||||||
ReturnValue = IPC_EINVAL;
|
return_value = IPC_EINVAL;
|
||||||
|
|
||||||
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
|
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
|
||||||
|
|
||||||
|
@ -217,14 +198,9 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
||||||
struct libusb_transfer* transfer = libusb_alloc_transfer(0);
|
struct libusb_transfer* transfer = libusb_alloc_transfer(0);
|
||||||
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||||
libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, Memory::GetPointer(data), length,
|
libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, Memory::GetPointer(data), length,
|
||||||
handleUsbUpdates, (void*)(size_t)_CommandAddress, 0);
|
handleUsbUpdates, (void*)(size_t)request.address, 0);
|
||||||
libusb_submit_transfer(transfer);
|
libusb_submit_transfer(transfer);
|
||||||
|
|
||||||
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt %s)(%d,%d,%X) (BufferIn: (%08x, %i), BufferOut:
|
|
||||||
// (%08x, %i)",
|
|
||||||
// Parameter == IOCTL_HID_INTERRUPT_IN ? "In" : "Out", endpoint, length, data,
|
|
||||||
// BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
|
|
||||||
// It's the async way!
|
// It's the async way!
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
|
@ -233,28 +209,21 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
|
||||||
std::lock_guard<std::mutex> lk(m_device_list_reply_mutex);
|
std::lock_guard<std::mutex> lk(m_device_list_reply_mutex);
|
||||||
if (deviceCommandAddress != 0)
|
if (deviceCommandAddress != 0)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18));
|
IOSIOCtlRequest pending_request{deviceCommandAddress};
|
||||||
|
Memory::Write_U32(0xFFFFFFFF, pending_request.buffer_out);
|
||||||
// Return value
|
WII_IPC_HLE_Interface::EnqueueReply(pending_request, -1);
|
||||||
Memory::Write_U32(-1, deviceCommandAddress + 4);
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(deviceCommandAddress);
|
|
||||||
deviceCommandAddress = 0;
|
deviceCommandAddress = 0;
|
||||||
}
|
}
|
||||||
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
||||||
BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
request.buffer_in, request.buffer_in_size, request.buffer_out,
|
||||||
|
request.buffer_out_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
request.Log(GetDeviceName(), LogTypes::WII_IPC_HID);
|
||||||
INFO_LOG(WII_IPC_HID, "HID::IOCtl(0x%x) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
|
||||||
Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
|
return GetDefaultReply(return_value);
|
||||||
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_hid::ClaimDevice(libusb_device_handle* dev)
|
bool CWII_IPC_HLE_Device_hid::ClaimDevice(libusb_device_handle* dev)
|
||||||
|
@ -283,26 +252,11 @@ bool CWII_IPC_HLE_Device_hid::ClaimDevice(libusb_device_handle* dev)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtlV(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING);
|
Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING);
|
||||||
u32 ReturnValue = 0;
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_HID);
|
||||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_HID, "%s - IOCtlV:", GetDeviceName().c_str());
|
|
||||||
INFO_LOG(WII_IPC_HID, " Parameter: 0x%x", CommandBuffer.Parameter);
|
|
||||||
INFO_LOG(WII_IPC_HID, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer);
|
|
||||||
INFO_LOG(WII_IPC_HID, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer);
|
|
||||||
INFO_LOG(WII_IPC_HID, " BufferVector: 0x%08x", CommandBuffer.BufferVector);
|
|
||||||
INFO_LOG(WII_IPC_HID, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address);
|
|
||||||
INFO_LOG(WII_IPC_HID, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size);
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer,
|
|
||||||
CommandBuffer.NumberPayloadBuffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_hid::ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest,
|
void CWII_IPC_HLE_Device_hid::ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest,
|
||||||
|
@ -344,10 +298,10 @@ void CWII_IPC_HLE_Device_hid::ConvertEndpointToWii(WiiHIDEndpointDescriptor* des
|
||||||
dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
|
dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize)
|
void CWII_IPC_HLE_Device_hid::FillOutDevices(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
static u16 check = 1;
|
static u16 check = 1;
|
||||||
int OffsetBuffer = BufferOut;
|
int OffsetBuffer = request.buffer_out;
|
||||||
int OffsetStart = 0;
|
int OffsetStart = 0;
|
||||||
// int OffsetDevice = 0;
|
// int OffsetDevice = 0;
|
||||||
int d, c, ic, i, e; /* config, interface container, interface, endpoint */
|
int d, c, ic, i, e; /* config, interface container, interface, endpoint */
|
||||||
|
|
|
@ -38,8 +38,8 @@ public:
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_hid();
|
virtual ~CWII_IPC_HLE_Device_hid();
|
||||||
|
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
|
@ -115,7 +115,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 deviceCommandAddress;
|
u32 deviceCommandAddress;
|
||||||
void FillOutDevices(u32 BufferOut, u32 BufferOutSize);
|
void FillOutDevices(const IOSIOCtlRequest& request);
|
||||||
int GetAvailableDevNum(u16 idVendor, u16 idProduct, u8 bus, u8 port, u16 check);
|
int GetAvailableDevNum(u16 idVendor, u16 idProduct, u8 bus, u8 port, u16 check);
|
||||||
bool ClaimDevice(libusb_device_handle* dev);
|
bool ClaimDevice(libusb_device_handle* dev);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_net_kd_request();
|
virtual ~CWII_IPC_HLE_Device_net_kd_request();
|
||||||
|
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
|
@ -86,35 +86,31 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_net_kd_time() {}
|
virtual ~CWII_IPC_HLE_Device_net_kd_time() {}
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override
|
||||||
{
|
{
|
||||||
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
|
s32 result = 0;
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
|
||||||
|
|
||||||
u32 result = 0;
|
|
||||||
u32 common_result = 0;
|
u32 common_result = 0;
|
||||||
// TODO Writes stuff to /shared2/nwc24/misc.bin
|
// TODO Writes stuff to /shared2/nwc24/misc.bin
|
||||||
// u32 update_misc = 0;
|
// u32 update_misc = 0;
|
||||||
|
|
||||||
switch (Parameter)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
case IOCTL_NW24_GET_UNIVERSAL_TIME:
|
case IOCTL_NW24_GET_UNIVERSAL_TIME:
|
||||||
Memory::Write_U64(GetAdjustedUTC(), BufferOut + 4);
|
Memory::Write_U64(GetAdjustedUTC(), request.buffer_out + 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_NW24_SET_UNIVERSAL_TIME:
|
case IOCTL_NW24_SET_UNIVERSAL_TIME:
|
||||||
SetAdjustedUTC(Memory::Read_U64(BufferIn));
|
SetAdjustedUTC(Memory::Read_U64(request.buffer_in));
|
||||||
// update_misc = Memory::Read_U32(BufferIn + 8);
|
// update_misc = Memory::Read_U32(request.buffer_in + 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_NW24_SET_RTC_COUNTER:
|
case IOCTL_NW24_SET_RTC_COUNTER:
|
||||||
rtc = Memory::Read_U32(BufferIn);
|
rtc = Memory::Read_U32(request.buffer_in);
|
||||||
// update_misc = Memory::Read_U32(BufferIn + 4);
|
// update_misc = Memory::Read_U32(request.buffer_in + 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_NW24_GET_TIME_DIFF:
|
case IOCTL_NW24_GET_TIME_DIFF:
|
||||||
Memory::Write_U64(GetAdjustedUTC() - rtc, BufferOut + 4);
|
Memory::Write_U64(GetAdjustedUTC() - rtc, request.buffer_out + 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_NW24_UNIMPLEMENTED:
|
case IOCTL_NW24_UNIMPLEMENTED:
|
||||||
|
@ -122,14 +118,13 @@ public:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_NET, "%s - unknown IOCtl: %x", GetDeviceName().c_str(), Parameter);
|
ERROR_LOG(WII_IPC_NET, "%s - unknown IOCtl: %x", GetDeviceName().c_str(), request.request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write return values
|
// write return values
|
||||||
Memory::Write_U32(common_result, BufferOut);
|
Memory::Write_U32(common_result, request.buffer_out);
|
||||||
Memory::Write_U32(result, _CommandAddress + 4);
|
return GetDefaultReply(result);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -207,8 +202,8 @@ public:
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_net_ip_top();
|
virtual ~CWII_IPC_HLE_Device_net_ip_top();
|
||||||
|
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
|
@ -227,7 +222,7 @@ public:
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_net_ncd_manage();
|
virtual ~CWII_IPC_HLE_Device_net_ncd_manage();
|
||||||
|
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
|
@ -253,7 +248,7 @@ public:
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_net_wd_command();
|
virtual ~CWII_IPC_HLE_Device_net_wd_command();
|
||||||
|
|
||||||
IPCCommandResult IOCtlV(u32 CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
|
|
|
@ -75,72 +75,58 @@ int CWII_IPC_HLE_Device_net_ssl::GetSSLFreeID() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtl(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
request.Log(GetDeviceName(), LogTypes::WII_IPC_SSL, LogTypes::LINFO);
|
||||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
|
||||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
|
||||||
u32 Command = Memory::Read_U32(_CommandAddress + 0x0C);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_SSL, "%s unknown %i "
|
|
||||||
"(BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
|
||||||
GetDeviceName().c_str(), Command, BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
u32 BufferIn = 0, BufferIn2 = 0, BufferIn3 = 0;
|
||||||
|
|
||||||
u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0;
|
|
||||||
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
|
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
|
||||||
|
|
||||||
u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0;
|
u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0;
|
||||||
u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0;
|
u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0;
|
||||||
|
|
||||||
if (CommandBuffer.InBuffer.size() > 0)
|
if (request.in_vectors.size() > 0)
|
||||||
{
|
{
|
||||||
_BufferIn = CommandBuffer.InBuffer.at(0).m_Address;
|
BufferIn = request.in_vectors.at(0).address;
|
||||||
BufferInSize = CommandBuffer.InBuffer.at(0).m_Size;
|
BufferInSize = request.in_vectors.at(0).size;
|
||||||
}
|
}
|
||||||
if (CommandBuffer.InBuffer.size() > 1)
|
if (request.in_vectors.size() > 1)
|
||||||
{
|
{
|
||||||
_BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address;
|
BufferIn2 = request.in_vectors.at(1).address;
|
||||||
BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size;
|
BufferInSize2 = request.in_vectors.at(1).size;
|
||||||
}
|
}
|
||||||
if (CommandBuffer.InBuffer.size() > 2)
|
if (request.in_vectors.size() > 2)
|
||||||
{
|
{
|
||||||
_BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address;
|
BufferIn3 = request.in_vectors.at(2).address;
|
||||||
BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size;
|
BufferInSize3 = request.in_vectors.at(2).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 0)
|
if (request.io_vectors.size() > 0)
|
||||||
{
|
{
|
||||||
BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
|
BufferOut = request.io_vectors.at(0).address;
|
||||||
BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
|
BufferOutSize = request.io_vectors.at(0).size;
|
||||||
}
|
}
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 1)
|
if (request.io_vectors.size() > 1)
|
||||||
{
|
{
|
||||||
BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
|
BufferOut2 = request.io_vectors.at(1).address;
|
||||||
BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
|
BufferOutSize2 = request.io_vectors.at(1).size;
|
||||||
}
|
}
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 2)
|
if (request.io_vectors.size() > 2)
|
||||||
{
|
{
|
||||||
BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address;
|
BufferOut3 = request.io_vectors.at(2).address;
|
||||||
BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size;
|
BufferOutSize3 = request.io_vectors.at(2).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// I don't trust SSL to be deterministic, and this is never going to sync
|
// 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 -
|
// as such (as opposed to forwarding IPC results or whatever), so -
|
||||||
if (Core::g_want_determinism)
|
if (Core::g_want_determinism)
|
||||||
{
|
return GetDefaultReply(IPC_EACCES);
|
||||||
Memory::Write_U32(-1, _CommandAddress + 0x4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (CommandBuffer.Parameter)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
case IOCTLV_NET_SSL_NEW:
|
case IOCTLV_NET_SSL_NEW:
|
||||||
{
|
{
|
||||||
|
@ -187,20 +173,20 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
mbedtls_ssl_set_hostname(&ssl->ctx, ssl->hostname.c_str());
|
mbedtls_ssl_set_hostname(&ssl->ctx, ssl->hostname.c_str());
|
||||||
|
|
||||||
ssl->active = true;
|
ssl->active = true;
|
||||||
Memory::Write_U32(freeSSL, _BufferIn);
|
Memory::Write_U32(freeSSL, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_SSL_NEW_ERROR:
|
_SSL_NEW_ERROR:
|
||||||
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
|
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_NEW (%d, %s) "
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_NEW (%d, %s) "
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
verifyOption, hostname.c_str(), _BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
verifyOption, hostname.c_str(), BufferIn, BufferInSize, BufferIn2, BufferInSize2,
|
||||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2,
|
BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2,
|
||||||
BufferOut3, BufferOutSize3);
|
BufferOut3, BufferOutSize3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -226,18 +212,18 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
ssl->active = false;
|
ssl->active = false;
|
||||||
|
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SHUTDOWN "
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SHUTDOWN "
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTLV_NET_SSL_SETROOTCA:
|
case IOCTLV_NET_SSL_SETROOTCA:
|
||||||
|
@ -246,8 +232,8 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
|
|
||||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
|
@ -264,19 +250,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
|
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mbedtls_ssl_conf_ca_chain(&ssl->config, &ssl->cacert, nullptr);
|
mbedtls_ssl_conf_ca_chain(&ssl->config, &ssl->cacert, nullptr);
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA = %d", ret);
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA = %d", ret);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -286,8 +272,8 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
|
|
||||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
|
@ -302,19 +288,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
mbedtls_x509_crt_free(&ssl->clicert);
|
mbedtls_x509_crt_free(&ssl->clicert);
|
||||||
mbedtls_pk_free(&ssl->pk);
|
mbedtls_pk_free(&ssl->pk);
|
||||||
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
|
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mbedtls_ssl_conf_own_cert(&ssl->config, &ssl->clicert, &ssl->pk);
|
mbedtls_ssl_conf_own_cert(&ssl->config, &ssl->clicert, &ssl->pk);
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = (%d, %d)", ret, pk_ret);
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = (%d, %d)", ret, pk_ret);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID);
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -325,8 +311,8 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
|
|
||||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
|
@ -336,11 +322,11 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
mbedtls_pk_free(&ssl->pk);
|
mbedtls_pk_free(&ssl->pk);
|
||||||
|
|
||||||
mbedtls_ssl_conf_own_cert(&ssl->config, nullptr, nullptr);
|
mbedtls_ssl_conf_own_cert(&ssl->config, nullptr, nullptr);
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID);
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -357,25 +343,25 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
mbedtls_x509_crt_free(&ssl->clicert);
|
mbedtls_x509_crt_free(&ssl->clicert);
|
||||||
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
|
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mbedtls_ssl_conf_ca_chain(&ssl->config, &ssl->cacert, nullptr);
|
mbedtls_ssl_conf_ca_chain(&ssl->config, &ssl->cacert, nullptr);
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA = %d", ret);
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA = %d", ret);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA "
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA "
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTLV_NET_SSL_CONNECT:
|
case IOCTLV_NET_SSL_CONNECT:
|
||||||
|
@ -388,18 +374,18 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
ssl->sockfd = Memory::Read_U32(BufferOut2);
|
ssl->sockfd = Memory::Read_U32(BufferOut2);
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT socket = %d", ssl->sockfd);
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT socket = %d", ssl->sockfd);
|
||||||
mbedtls_ssl_set_bio(&ssl->ctx, &ssl->sockfd, mbedtls_net_send, mbedtls_net_recv, nullptr);
|
mbedtls_ssl_set_bio(&ssl->ctx, &ssl->sockfd, mbedtls_net_send, mbedtls_net_recv, nullptr);
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT "
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT "
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTLV_NET_SSL_DOHANDSHAKE:
|
case IOCTLV_NET_SSL_DOHANDSHAKE:
|
||||||
|
@ -408,12 +394,12 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
{
|
{
|
||||||
WiiSockMan& sm = WiiSockMan::GetInstance();
|
WiiSockMan& sm = WiiSockMan::GetInstance();
|
||||||
sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_DOHANDSHAKE);
|
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_DOHANDSHAKE);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -423,19 +409,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
{
|
{
|
||||||
WiiSockMan& sm = WiiSockMan::GetInstance();
|
WiiSockMan& sm = WiiSockMan::GetInstance();
|
||||||
sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_WRITE);
|
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_WRITE);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_WRITE "
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_WRITE "
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
INFO_LOG(WII_IPC_SSL, "%s", Memory::GetString(BufferOut2).c_str());
|
INFO_LOG(WII_IPC_SSL, "%s", Memory::GetString(BufferOut2).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -446,19 +432,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
{
|
{
|
||||||
WiiSockMan& sm = WiiSockMan::GetInstance();
|
WiiSockMan& sm = WiiSockMan::GetInstance();
|
||||||
sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_READ);
|
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_READ);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ(%d)"
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ(%d)"
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
ret, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
ret, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -467,18 +453,18 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCADEFAULT "
|
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCADEFAULT "
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT:
|
case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT:
|
||||||
|
@ -487,33 +473,24 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||||
|
|
||||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||||
if (SSLID_VALID(sslID))
|
if (SSLID_VALID(sslID))
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
Memory::Write_U32(SSL_OK, BufferIn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_SSL, "%i "
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_SSL);
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
|
||||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
|
||||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
|
||||||
CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
|
||||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2,
|
|
||||||
BufferOut3, BufferOutSize3);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSL return codes are written to BufferIn
|
// SSL return codes are written to BufferIn
|
||||||
Memory::Write_U32(0, _CommandAddress + 4);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,8 @@ public:
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_net_ssl();
|
virtual ~CWII_IPC_HLE_Device_net_ssl();
|
||||||
|
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
|
||||||
int GetSSLFreeID() const;
|
int GetSSLFreeID() const;
|
||||||
|
|
||||||
|
|
|
@ -38,15 +38,15 @@ void CWII_IPC_HLE_Device_sdio_slot0::DoState(PointerWrap& p)
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
|
void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
|
||||||
{
|
{
|
||||||
|
if (!m_event)
|
||||||
|
return;
|
||||||
// Accessing SConfig variables like this isn't really threadsafe,
|
// Accessing SConfig variables like this isn't really threadsafe,
|
||||||
// but this is how it's done all over the place...
|
// but this is how it's done all over the place...
|
||||||
if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) ||
|
if ((SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_INSERT) ||
|
||||||
(!SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_REMOVE))
|
(!SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_REMOVE))
|
||||||
{
|
{
|
||||||
Memory::Write_U32(m_event.type, m_event.addr + 4);
|
WII_IPC_HLE_Interface::EnqueueReply(m_event->request, m_event->type);
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_event.addr);
|
m_event.reset();
|
||||||
m_event.addr = 0;
|
|
||||||
m_event.type = EVENT_NONE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,50 +70,35 @@ void CWII_IPC_HLE_Device_sdio_slot0::OpenInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode)
|
IOSReturnCode CWII_IPC_HLE_Device_sdio_slot0::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_SD, "Open");
|
|
||||||
|
|
||||||
OpenInternal();
|
OpenInternal();
|
||||||
|
|
||||||
m_registers.fill(0);
|
m_registers.fill(0);
|
||||||
|
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetDefaultReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::Close(u32 _CommandAddress, bool _bForce)
|
void CWII_IPC_HLE_Device_sdio_slot0::Close()
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_SD, "Close");
|
|
||||||
|
|
||||||
m_Card.Close();
|
m_Card.Close();
|
||||||
m_BlockLength = 0;
|
m_BlockLength = 0;
|
||||||
m_BusWidth = 0;
|
m_BusWidth = 0;
|
||||||
|
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The front SD slot
|
// The front SD slot
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
u32 Cmd = Memory::Read_U32(_CommandAddress + 0xC);
|
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
|
||||||
|
s32 return_value = IPC_SUCCESS;
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
switch (request.request)
|
||||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
|
||||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
|
||||||
|
|
||||||
// As a safety precaution we fill the out buffer with zeros to avoid
|
|
||||||
// returning nonsense values
|
|
||||||
Memory::Memset(BufferOut, 0, BufferOutSize);
|
|
||||||
|
|
||||||
u32 ReturnValue = 0;
|
|
||||||
switch (Cmd)
|
|
||||||
{
|
{
|
||||||
case IOCTL_WRITEHCR:
|
case IOCTL_WRITEHCR:
|
||||||
{
|
{
|
||||||
u32 reg = Memory::Read_U32(BufferIn);
|
u32 reg = Memory::Read_U32(request.buffer_in);
|
||||||
u32 val = Memory::Read_U32(BufferIn + 16);
|
u32 val = Memory::Read_U32(request.buffer_in + 16);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);
|
INFO_LOG(WII_IPC_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);
|
||||||
|
|
||||||
|
@ -143,7 +128,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_READHCR:
|
case IOCTL_READHCR:
|
||||||
{
|
{
|
||||||
u32 reg = Memory::Read_U32(BufferIn);
|
u32 reg = Memory::Read_U32(request.buffer_in);
|
||||||
|
|
||||||
if (reg >= m_registers.size())
|
if (reg >= m_registers.size())
|
||||||
{
|
{
|
||||||
|
@ -155,7 +140,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
|
INFO_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
|
||||||
|
|
||||||
// Just reading the register
|
// Just reading the register
|
||||||
Memory::Write_U32(val, BufferOut);
|
Memory::Write_U32(val, request.buffer_out);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -164,7 +149,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
if (m_Card)
|
if (m_Card)
|
||||||
m_Status |= CARD_INITIALIZED;
|
m_Status |= CARD_INITIALIZED;
|
||||||
// Returns 16bit RCA and 16bit 0s (meaning success)
|
// Returns 16bit RCA and 16bit 0s (meaning success)
|
||||||
Memory::Write_U32(0x9f620000, BufferOut);
|
Memory::Write_U32(0x9f620000, request.buffer_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_SETCLK:
|
case IOCTL_SETCLK:
|
||||||
|
@ -172,15 +157,17 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_SETCLK");
|
INFO_LOG(WII_IPC_SD, "IOCTL_SETCLK");
|
||||||
// libogc only sets it to 1 and makes sure the return isn't negative...
|
// libogc only sets it to 1 and makes sure the return isn't negative...
|
||||||
// one half of the sdclk divisor: a power of two or zero.
|
// one half of the sdclk divisor: a power of two or zero.
|
||||||
u32 clock = Memory::Read_U32(BufferIn);
|
u32 clock = Memory::Read_U32(request.buffer_in);
|
||||||
if (clock != 1)
|
if (clock != 1)
|
||||||
INFO_LOG(WII_IPC_SD, "Setting to %i, interesting", clock);
|
INFO_LOG(WII_IPC_SD, "Setting to %i, interesting", clock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_SENDCMD:
|
case IOCTL_SENDCMD:
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(BufferIn), _CommandAddress);
|
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(request.buffer_in),
|
||||||
ReturnValue = ExecuteCommand(BufferIn, BufferInSize, 0, 0, BufferOut, BufferOutSize);
|
request.address);
|
||||||
|
return_value = ExecuteCommand(request, request.buffer_in, request.buffer_in_size, 0, 0,
|
||||||
|
request.buffer_out, request.buffer_out_size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_GETSTATUS:
|
case IOCTL_GETSTATUS:
|
||||||
|
@ -191,89 +178,51 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_GETSTATUS. Replying that SD card is %s%s",
|
INFO_LOG(WII_IPC_SD, "IOCTL_GETSTATUS. Replying that SD card is %s%s",
|
||||||
(m_Status & CARD_INSERTED) ? "inserted" : "not present",
|
(m_Status & CARD_INSERTED) ? "inserted" : "not present",
|
||||||
(m_Status & CARD_INITIALIZED) ? " and initialized" : "");
|
(m_Status & CARD_INITIALIZED) ? " and initialized" : "");
|
||||||
Memory::Write_U32(m_Status, BufferOut);
|
Memory::Write_U32(m_Status, request.buffer_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_GETOCR:
|
case IOCTL_GETOCR:
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_GETOCR");
|
INFO_LOG(WII_IPC_SD, "IOCTL_GETOCR");
|
||||||
Memory::Write_U32(0x80ff8000, BufferOut);
|
Memory::Write_U32(0x80ff8000, request.buffer_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtl command (0x%08x)", Cmd);
|
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtl command (0x%08x)", request.request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INFO_LOG(WII_IPC_SD, "InBuffer");
|
if (return_value == RET_EVENT_REGISTER)
|
||||||
// DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_SD);
|
|
||||||
// INFO_LOG(WII_IPC_SD, "OutBuffer");
|
|
||||||
// DumpCommands(BufferOut, BufferOutSize/4, LogTypes::WII_IPC_SD);
|
|
||||||
|
|
||||||
if (ReturnValue == RET_EVENT_REGISTER)
|
|
||||||
{
|
{
|
||||||
// async
|
|
||||||
m_event.addr = _CommandAddress;
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
// Check if the condition is already true
|
// Check if the condition is already true
|
||||||
EventNotify();
|
EventNotify();
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
else if (ReturnValue == RET_EVENT_UNREGISTER)
|
return GetDefaultReply(return_value);
|
||||||
{
|
|
||||||
// release returns 0
|
|
||||||
// unknown sd int
|
|
||||||
// technically we do it out of order, oh well
|
|
||||||
Memory::Write_U32(EVENT_INVALID, m_event.addr + 4);
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_event.addr);
|
|
||||||
m_event.addr = 0;
|
|
||||||
m_event.type = EVENT_NONE;
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
// PPC sending commands
|
s32 return_value = IPC_SUCCESS;
|
||||||
|
switch (request.request)
|
||||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
|
||||||
|
|
||||||
// Prepare the out buffer(s) with zeros as a safety precaution
|
|
||||||
// to avoid returning bad values
|
|
||||||
for (const auto& buffer : CommandBuffer.PayloadBuffer)
|
|
||||||
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
|
|
||||||
|
|
||||||
u32 ReturnValue = 0;
|
|
||||||
switch (CommandBuffer.Parameter)
|
|
||||||
{
|
{
|
||||||
case IOCTLV_SENDCMD:
|
case IOCTLV_SENDCMD:
|
||||||
DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x",
|
DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(request.in_vectors[0].address));
|
||||||
Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address));
|
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
|
||||||
ReturnValue = ExecuteCommand(
|
return_value =
|
||||||
CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size,
|
ExecuteCommand(request, request.in_vectors[0].address, request.in_vectors[0].size,
|
||||||
CommandBuffer.InBuffer[1].m_Address, CommandBuffer.InBuffer[1].m_Size,
|
request.in_vectors[1].address, request.in_vectors[1].size,
|
||||||
CommandBuffer.PayloadBuffer[0].m_Address, CommandBuffer.PayloadBuffer[0].m_Size);
|
request.io_vectors[0].address, request.io_vectors[0].size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", CommandBuffer.Parameter);
|
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", request.request);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer,
|
return GetDefaultReply(return_value);
|
||||||
// CommandBuffer.NumberPayloadBuffer, LogTypes::WII_IPC_SD);
|
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
|
||||||
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 _rwBuffer,
|
u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(const IOSRequest& request, u32 _BufferIn,
|
||||||
|
u32 _BufferInSize, u32 _rwBuffer,
|
||||||
u32 _rwBufferSize, u32 _BufferOut,
|
u32 _rwBufferSize, u32 _BufferOut,
|
||||||
u32 _BufferOutSize)
|
u32 _BufferOutSize)
|
||||||
{
|
{
|
||||||
|
@ -429,15 +378,23 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
|
||||||
|
|
||||||
case EVENT_REGISTER: // async
|
case EVENT_REGISTER: // async
|
||||||
INFO_LOG(WII_IPC_SD, "Register event %x", req.arg);
|
INFO_LOG(WII_IPC_SD, "Register event %x", req.arg);
|
||||||
m_event.type = (EventType)req.arg;
|
m_event = std::make_unique<Event>(static_cast<EventType>(req.arg), request);
|
||||||
ret = RET_EVENT_REGISTER;
|
ret = RET_EVENT_REGISTER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EVENT_UNREGISTER: // synchronous
|
// Used to cancel an event that was already registered.
|
||||||
|
case EVENT_UNREGISTER:
|
||||||
|
{
|
||||||
INFO_LOG(WII_IPC_SD, "Unregister event %x", req.arg);
|
INFO_LOG(WII_IPC_SD, "Unregister event %x", req.arg);
|
||||||
m_event.type = (EventType)req.arg;
|
if (!m_event)
|
||||||
ret = RET_EVENT_UNREGISTER;
|
return IPC_EINVAL;
|
||||||
|
// release returns 0
|
||||||
|
// unknown sd int
|
||||||
|
// technically we do it out of order, oh well
|
||||||
|
WII_IPC_HLE_Interface::EnqueueReply(m_event->request, EVENT_INVALID);
|
||||||
|
m_event.reset();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_SD, "Unknown SD command 0x%08x", req.command);
|
ERROR_LOG(WII_IPC_SD, "Unknown SD command 0x%08x", req.command);
|
||||||
|
|
|
@ -23,11 +23,10 @@ public:
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
|
void Close() override;
|
||||||
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
|
||||||
|
|
||||||
void EventNotify();
|
void EventNotify();
|
||||||
|
|
||||||
|
@ -63,7 +62,6 @@ private:
|
||||||
RET_OK,
|
RET_OK,
|
||||||
RET_FAIL,
|
RET_FAIL,
|
||||||
RET_EVENT_REGISTER, // internal state only - not actually returned
|
RET_EVENT_REGISTER, // internal state only - not actually returned
|
||||||
RET_EVENT_UNREGISTER
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
|
@ -100,9 +98,8 @@ private:
|
||||||
|
|
||||||
enum EventType
|
enum EventType
|
||||||
{
|
{
|
||||||
EVENT_NONE = 0,
|
EVENT_INSERT = 1,
|
||||||
EVENT_INSERT,
|
EVENT_REMOVE = 2,
|
||||||
EVENT_REMOVE,
|
|
||||||
// from unregister, i think it is just meant to be invalid
|
// from unregister, i think it is just meant to be invalid
|
||||||
EVENT_INVALID = 0xc210000
|
EVENT_INVALID = 0xc210000
|
||||||
};
|
};
|
||||||
|
@ -110,9 +107,11 @@ private:
|
||||||
// TODO do we need more than one?
|
// TODO do we need more than one?
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
EventType type = EVENT_NONE;
|
Event(EventType type_, IOSRequest request_) : type(type_), request(request_) {}
|
||||||
u32 addr = 0;
|
EventType type;
|
||||||
} m_event;
|
IOSRequest request;
|
||||||
|
};
|
||||||
|
std::unique_ptr<Event> m_event;
|
||||||
|
|
||||||
u32 m_Status = CARD_NOT_EXIST;
|
u32 m_Status = CARD_NOT_EXIST;
|
||||||
u32 m_BlockLength = 0;
|
u32 m_BlockLength = 0;
|
||||||
|
@ -122,7 +121,7 @@ private:
|
||||||
|
|
||||||
File::IOFile m_Card;
|
File::IOFile m_Card;
|
||||||
|
|
||||||
u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 BufferIn2, u32 BufferInSize2,
|
u32 ExecuteCommand(const IOSRequest& request, u32 BufferIn, u32 BufferInSize, u32 BufferIn2,
|
||||||
u32 _BufferOut, u32 BufferOutSize);
|
u32 BufferInSize2, u32 _BufferOut, u32 BufferOutSize);
|
||||||
void OpenInternal();
|
void OpenInternal();
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
@ -16,22 +17,12 @@ void QueueHostJob(std::function<void()> job, bool run_during_stop);
|
||||||
void Stop();
|
void Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 s_event_hook_address = 0;
|
static std::unique_ptr<IOSIOCtlRequest> s_event_hook_request;
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address)
|
IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
u32 parameter = Memory::Read_U32(command_address + 0x0C);
|
s32 return_value = IPC_SUCCESS;
|
||||||
u32 buffer_in = Memory::Read_U32(command_address + 0x10);
|
switch (request.request)
|
||||||
u32 buffer_in_size = Memory::Read_U32(command_address + 0x14);
|
|
||||||
u32 buffer_out = Memory::Read_U32(command_address + 0x18);
|
|
||||||
u32 buffer_out_size = Memory::Read_U32(command_address + 0x1C);
|
|
||||||
|
|
||||||
// Prepare the out buffer(s) with zeroes as a safety precaution
|
|
||||||
// to avoid returning bad values
|
|
||||||
Memory::Memset(buffer_out, 0, buffer_out_size);
|
|
||||||
u32 return_value = 0;
|
|
||||||
|
|
||||||
switch (parameter)
|
|
||||||
{
|
{
|
||||||
case IOCTL_STM_IDLE:
|
case IOCTL_STM_IDLE:
|
||||||
case IOCTL_STM_SHUTDOWN:
|
case IOCTL_STM_SHUTDOWN:
|
||||||
|
@ -40,15 +31,14 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_STM_RELEASE_EH:
|
case IOCTL_STM_RELEASE_EH:
|
||||||
if (s_event_hook_address == 0)
|
if (!s_event_hook_request)
|
||||||
{
|
{
|
||||||
return_value = IPC_ENOENT;
|
return_value = IPC_ENOENT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Memory::Write_U32(0, Memory::Read_U32(s_event_hook_address + 0x18));
|
Memory::Write_U32(0, s_event_hook_request->buffer_out);
|
||||||
Memory::Write_U32(IPC_SUCCESS, s_event_hook_address + 4);
|
WII_IPC_HLE_Interface::EnqueueReply(*s_event_hook_request, IPC_SUCCESS);
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(s_event_hook_address);
|
s_event_hook_request.reset();
|
||||||
s_event_hook_address = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_STM_HOTRESET:
|
case IOCTL_STM_HOTRESET:
|
||||||
|
@ -59,7 +49,6 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address)
|
||||||
case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes)
|
case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes)
|
||||||
INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str());
|
INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str());
|
||||||
INFO_LOG(WII_IPC_STM, " IOCTL_STM_VIDIMMING");
|
INFO_LOG(WII_IPC_STM, " IOCTL_STM_VIDIMMING");
|
||||||
// DumpCommands(buffer_in, buffer_in_size / 4, LogTypes::WII_IPC_STM);
|
|
||||||
// Memory::Write_U32(1, buffer_out);
|
// Memory::Write_U32(1, buffer_out);
|
||||||
// return_value = 1;
|
// return_value = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -70,79 +59,53 @@ IPCCommandResult CWII_IPC_HLE_Device_stm_immediate::IOCtl(u32 command_address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_STM);
|
||||||
_dbg_assert_msg_(WII_IPC_STM, 0, "CWII_IPC_HLE_Device_stm_immediate: 0x%x", parameter);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_STM, "%s - IOCtl:", GetDeviceName().c_str());
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " parameter: 0x%x", parameter);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " InBuffer: 0x%08x", buffer_in);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " InBufferSize: 0x%08x", buffer_in_size);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " OutBuffer: 0x%08x", buffer_out);
|
|
||||||
DEBUG_LOG(WII_IPC_STM, " OutBufferSize: 0x%08x", buffer_out_size);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write return value to the IPC call
|
return GetDefaultReply(return_value);
|
||||||
Memory::Write_U32(return_value, command_address + 0x4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::Close(u32 command_address, bool force)
|
void CWII_IPC_HLE_Device_stm_eventhook::Close()
|
||||||
{
|
{
|
||||||
s_event_hook_address = 0;
|
s_event_hook_request.reset();
|
||||||
|
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(u32 command_address)
|
IPCCommandResult CWII_IPC_HLE_Device_stm_eventhook::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
u32 parameter = Memory::Read_U32(command_address + 0x0C);
|
if (request.request != IOCTL_STM_EVENTHOOK)
|
||||||
if (parameter != IOCTL_STM_EVENTHOOK)
|
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_STM, "Bad IOCtl in CWII_IPC_HLE_Device_stm_eventhook");
|
ERROR_LOG(WII_IPC_STM, "Bad IOCtl in CWII_IPC_HLE_Device_stm_eventhook");
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address + 4);
|
return GetDefaultReply(IPC_EINVAL);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_event_hook_address != 0)
|
if (s_event_hook_request)
|
||||||
{
|
return GetDefaultReply(IPC_EEXIST);
|
||||||
Memory::Write_U32(FS_EEXIST, command_address + 4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
// IOCTL_STM_EVENTHOOK waits until the reset button or power button
|
// IOCTL_STM_EVENTHOOK waits until the reset button or power button is pressed.
|
||||||
// is pressed.
|
s_event_hook_request = std::make_unique<IOSIOCtlRequest>(request.address);
|
||||||
s_event_hook_address = command_address;
|
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_stm_eventhook::HasHookInstalled() const
|
bool CWII_IPC_HLE_Device_stm_eventhook::HasHookInstalled() const
|
||||||
{
|
{
|
||||||
return s_event_hook_address != 0;
|
return s_event_hook_request != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_stm_eventhook::TriggerEvent(const u32 event) const
|
void CWII_IPC_HLE_Device_stm_eventhook::TriggerEvent(const u32 event) const
|
||||||
{
|
{
|
||||||
if (!m_is_active || s_event_hook_address == 0)
|
// If the device isn't open, ignore the button press.
|
||||||
{
|
if (!m_is_active || !s_event_hook_request)
|
||||||
// If the device isn't open, ignore the button press.
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// The reset button returns STM_EVENT_RESET.
|
Memory::Write_U32(event, s_event_hook_request->buffer_out);
|
||||||
u32 buffer_out = Memory::Read_U32(s_event_hook_address + 0x18);
|
WII_IPC_HLE_Interface::EnqueueReply(*s_event_hook_request, IPC_SUCCESS);
|
||||||
Memory::Write_U32(event, buffer_out);
|
s_event_hook_request.reset();
|
||||||
|
|
||||||
Memory::Write_U32(IPC_SUCCESS, s_event_hook_address + 4);
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(s_event_hook_address);
|
|
||||||
s_event_hook_address = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const
|
void CWII_IPC_HLE_Device_stm_eventhook::ResetButton() const
|
||||||
{
|
{
|
||||||
// The reset button returns STM_EVENT_RESET.
|
// The reset button triggers STM_EVENT_RESET.
|
||||||
TriggerEvent(STM_EVENT_RESET);
|
TriggerEvent(STM_EVENT_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~CWII_IPC_HLE_Device_stm_immediate() override = default;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtl(u32 command_address) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The /dev/stm/eventhook
|
// The /dev/stm/eventhook
|
||||||
|
@ -56,9 +55,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~CWII_IPC_HLE_Device_stm_eventhook() override = default;
|
void Close() override;
|
||||||
IPCCommandResult Close(u32 command_address, bool force) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtl(u32 command_address) override;
|
|
||||||
|
|
||||||
bool HasHookInstalled() const;
|
bool HasHookInstalled() const;
|
||||||
void ResetButton() const;
|
void ResetButton() const;
|
||||||
|
|
|
@ -4,37 +4,33 @@
|
||||||
|
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_stub.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE_Device_stub.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Core/HW/Memmap.h"
|
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_stub::CWII_IPC_HLE_Device_stub(u32 device_id, const std::string& device_name)
|
CWII_IPC_HLE_Device_stub::CWII_IPC_HLE_Device_stub(u32 device_id, const std::string& device_name)
|
||||||
: IWII_IPC_HLE_Device(device_id, device_name)
|
: IWII_IPC_HLE_Device(device_id, device_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_stub::Open(u32 command_address, u32 mode)
|
IOSReturnCode CWII_IPC_HLE_Device_stub::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_HLE, "%s faking Open()", m_name.c_str());
|
WARN_LOG(WII_IPC_HLE, "%s faking Open()", m_name.c_str());
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetDefaultReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_stub::Close(u32 command_address, bool force)
|
void CWII_IPC_HLE_Device_stub::Close()
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_HLE, "%s faking Close()", m_name.c_str());
|
WARN_LOG(WII_IPC_HLE, "%s faking Close()", m_name.c_str());
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_stub::IOCtl(u32 command_address)
|
IPCCommandResult CWII_IPC_HLE_Device_stub::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_HLE, "%s faking IOCtl()", m_name.c_str());
|
WARN_LOG(WII_IPC_HLE, "%s faking IOCtl()", m_name.c_str());
|
||||||
Memory::Write_U32(IPC_SUCCESS, command_address + 4);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_stub::IOCtlV(u32 command_address)
|
IPCCommandResult CWII_IPC_HLE_Device_stub::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
WARN_LOG(WII_IPC_HLE, "%s faking IOCtlV()", m_name.c_str());
|
WARN_LOG(WII_IPC_HLE, "%s faking IOCtlV()", m_name.c_str());
|
||||||
Memory::Write_U32(IPC_SUCCESS, command_address + 4);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ class CWII_IPC_HLE_Device_stub : public IWII_IPC_HLE_Device
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_stub(u32 device_id, const std::string& device_name);
|
CWII_IPC_HLE_Device_stub(u32 device_id, const std::string& device_name);
|
||||||
|
|
||||||
IPCCommandResult Open(u32 command_address, u32 mode) override;
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Close(u32 command_address, bool force = false) override;
|
void Close() override;
|
||||||
IPCCommandResult IOCtl(u32 command_address) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 command_address) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,24 +50,23 @@ void RestoreBTInfoSection(SysConf* sysconf)
|
||||||
File::Delete(filename);
|
File::Delete(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlMessage::CtrlMessage(const SIOCtlVBuffer& cmd_buffer)
|
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlMessage::CtrlMessage(const IOSIOCtlVRequest& ioctlv)
|
||||||
|
: ios_request(ioctlv)
|
||||||
{
|
{
|
||||||
request_type = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
|
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address);
|
||||||
request = Memory::Read_U8(cmd_buffer.InBuffer[1].m_Address);
|
request = Memory::Read_U8(ioctlv.in_vectors[1].address);
|
||||||
value = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[2].m_Address));
|
value = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[2].address));
|
||||||
index = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[3].m_Address));
|
index = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[3].address));
|
||||||
length = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[4].m_Address));
|
length = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address));
|
||||||
payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
|
payload_addr = ioctlv.io_vectors[0].address;
|
||||||
address = cmd_buffer.m_Address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::CtrlBuffer(const SIOCtlVBuffer& cmd_buffer,
|
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::CtrlBuffer(const IOSIOCtlVRequest& ioctlv)
|
||||||
const u32 command_address)
|
: ios_request(ioctlv)
|
||||||
{
|
{
|
||||||
m_endpoint = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
|
m_endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
|
||||||
m_length = Memory::Read_U16(cmd_buffer.InBuffer[1].m_Address);
|
m_length = Memory::Read_U16(ioctlv.in_vectors[1].address);
|
||||||
m_payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
|
m_payload_addr = ioctlv.io_vectors[0].address;
|
||||||
m_cmd_address = command_address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::FillBuffer(const u8* src,
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::FillBuffer(const u8* src,
|
||||||
|
@ -77,8 +76,3 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::FillBuffer(const u8*
|
||||||
m_length);
|
m_length);
|
||||||
Memory::CopyToEmu(m_payload_addr, src, size);
|
Memory::CopyToEmu(m_payload_addr, src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::SetRetVal(const u32 retval) const
|
|
||||||
{
|
|
||||||
Memory::Write_U32(retval, m_cmd_address + 4);
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,11 +24,6 @@ public:
|
||||||
: IWII_IPC_HLE_Device(device_id, device_name)
|
: IWII_IPC_HLE_Device(device_id, device_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_base() override = default;
|
|
||||||
|
|
||||||
virtual IPCCommandResult Open(u32 command_address, u32 mode) override = 0;
|
|
||||||
|
|
||||||
virtual void DoState(PointerWrap& p) override = 0;
|
|
||||||
|
|
||||||
virtual void UpdateSyncButtonState(bool is_held) {}
|
virtual void UpdateSyncButtonState(bool is_held) {}
|
||||||
virtual void TriggerSyncButtonPressedEvent() {}
|
virtual void TriggerSyncButtonPressedEvent() {}
|
||||||
|
@ -56,31 +51,23 @@ protected:
|
||||||
|
|
||||||
struct CtrlMessage
|
struct CtrlMessage
|
||||||
{
|
{
|
||||||
CtrlMessage() = default;
|
CtrlMessage(const IOSIOCtlVRequest& ioctlv);
|
||||||
CtrlMessage(const SIOCtlVBuffer& cmd_buffer);
|
IOSIOCtlVRequest ios_request;
|
||||||
|
|
||||||
u8 request_type = 0;
|
u8 request_type = 0;
|
||||||
u8 request = 0;
|
u8 request = 0;
|
||||||
u16 value = 0;
|
u16 value = 0;
|
||||||
u16 index = 0;
|
u16 index = 0;
|
||||||
u16 length = 0;
|
u16 length = 0;
|
||||||
u32 payload_addr = 0;
|
u32 payload_addr = 0;
|
||||||
u32 address = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CtrlBuffer
|
struct CtrlBuffer
|
||||||
{
|
{
|
||||||
public:
|
CtrlBuffer(const IOSIOCtlVRequest& ioctlv);
|
||||||
CtrlBuffer() = default;
|
IOSIOCtlVRequest ios_request;
|
||||||
CtrlBuffer(const SIOCtlVBuffer& cmd_buffer, u32 command_address);
|
|
||||||
|
|
||||||
void FillBuffer(const u8* src, size_t size) const;
|
void FillBuffer(const u8* src, size_t size) const;
|
||||||
void SetRetVal(const u32 retval) const;
|
|
||||||
bool IsValid() const { return m_cmd_address != 0; }
|
|
||||||
void Invalidate() { m_cmd_address = m_payload_addr = 0; }
|
|
||||||
u8 m_endpoint = 0;
|
u8 m_endpoint = 0;
|
||||||
u16 m_length = 0;
|
u16 m_length = 0;
|
||||||
u32 m_payload_addr = 0;
|
u32 m_payload_addr = 0;
|
||||||
u32 m_cmd_address = 0;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -95,8 +95,6 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CWII_IPC_HLE_Device_usb_oh1_57e_305_emu
|
||||||
m_ControllerBD.b[4] = 0x00;
|
m_ControllerBD.b[4] = 0x00;
|
||||||
m_ControllerBD.b[5] = 0xFF;
|
m_ControllerBD.b[5] = 0xFF;
|
||||||
|
|
||||||
memset(m_PacketCount, 0, sizeof(m_PacketCount));
|
|
||||||
|
|
||||||
Host_SetWiiMoteConnectionState(0);
|
Host_SetWiiMoteConnectionState(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +104,18 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::~CWII_IPC_HLE_Device_usb_oh1_57e_305_em
|
||||||
SetUsbPointer(nullptr);
|
SetUsbPointer(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void DoStateForMessage(PointerWrap& p, std::unique_ptr<T>& message)
|
||||||
|
{
|
||||||
|
u32 request_address = (message != nullptr) ? message->ios_request.address : 0;
|
||||||
|
p.Do(request_address);
|
||||||
|
if (request_address != 0)
|
||||||
|
{
|
||||||
|
IOSIOCtlVRequest request{request_address};
|
||||||
|
message = std::make_unique<T>(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::DoState(PointerWrap& p)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
bool passthrough_bluetooth = false;
|
bool passthrough_bluetooth = false;
|
||||||
|
@ -119,10 +129,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::DoState(PointerWrap& p)
|
||||||
|
|
||||||
p.Do(m_is_active);
|
p.Do(m_is_active);
|
||||||
p.Do(m_ControllerBD);
|
p.Do(m_ControllerBD);
|
||||||
p.Do(m_CtrlSetup);
|
DoStateForMessage(p, m_CtrlSetup);
|
||||||
p.Do(m_ACLSetup);
|
DoStateForMessage(p, m_HCIEndpoint);
|
||||||
p.DoPOD(m_HCIEndpoint);
|
DoStateForMessage(p, m_ACLEndpoint);
|
||||||
p.DoPOD(m_ACLEndpoint);
|
|
||||||
p.Do(m_last_ticks);
|
p.Do(m_last_ticks);
|
||||||
p.DoArray(m_PacketCount);
|
p.DoArray(m_PacketCount);
|
||||||
p.Do(m_ScanEnable);
|
p.Do(m_ScanEnable);
|
||||||
|
@ -138,75 +147,41 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::RemoteDisconnect(u16 _connectionHa
|
||||||
return SendEventDisconnect(_connectionHandle, 0x13);
|
return SendEventDisconnect(_connectionHandle, 0x13);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Open(u32 _CommandAddress, u32 _Mode)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Close()
|
||||||
{
|
{
|
||||||
|
// Clean up state
|
||||||
m_ScanEnable = 0;
|
m_ScanEnable = 0;
|
||||||
|
|
||||||
m_last_ticks = 0;
|
m_last_ticks = 0;
|
||||||
memset(m_PacketCount, 0, sizeof(m_PacketCount));
|
memset(m_PacketCount, 0, sizeof(m_PacketCount));
|
||||||
|
m_HCIEndpoint.reset();
|
||||||
m_HCIEndpoint.m_cmd_address = 0;
|
m_ACLEndpoint.reset();
|
||||||
m_ACLEndpoint.m_cmd_address = 0;
|
|
||||||
|
|
||||||
m_is_active = true;
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Close(u32 _CommandAddress, bool _bForce)
|
|
||||||
{
|
|
||||||
m_ScanEnable = 0;
|
|
||||||
|
|
||||||
m_last_ticks = 0;
|
|
||||||
memset(m_PacketCount, 0, sizeof(m_PacketCount));
|
|
||||||
|
|
||||||
m_HCIEndpoint.m_cmd_address = 0;
|
|
||||||
m_ACLEndpoint.m_cmd_address = 0;
|
|
||||||
|
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtlV(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
bool _SendReply = false;
|
bool send_reply = true;
|
||||||
|
switch (request.request)
|
||||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
|
||||||
|
|
||||||
switch (CommandBuffer.Parameter)
|
|
||||||
{
|
{
|
||||||
case USBV0_IOCTL_CTRLMSG: // HCI command is received from the stack
|
case USBV0_IOCTL_CTRLMSG: // HCI command is received from the stack
|
||||||
{
|
{
|
||||||
// This is the HCI datapath from CPU to Wii Remote, the USB stuff is little endian..
|
m_CtrlSetup = std::make_unique<CtrlMessage>(request);
|
||||||
m_CtrlSetup.bRequestType = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address);
|
|
||||||
m_CtrlSetup.bRequest = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[1].m_Address);
|
|
||||||
m_CtrlSetup.wValue = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[2].m_Address);
|
|
||||||
m_CtrlSetup.wIndex = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[3].m_Address);
|
|
||||||
m_CtrlSetup.wLength = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[4].m_Address);
|
|
||||||
m_CtrlSetup.m_PayLoadAddr = CommandBuffer.PayloadBuffer[0].m_Address;
|
|
||||||
m_CtrlSetup.m_PayLoadSize = CommandBuffer.PayloadBuffer[0].m_Size;
|
|
||||||
m_CtrlSetup.m_Address = CommandBuffer.m_Address;
|
|
||||||
|
|
||||||
// check termination
|
|
||||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
|
||||||
*(u8*)Memory::GetPointer(CommandBuffer.InBuffer[5].m_Address) == 0,
|
|
||||||
"WIIMOTE: Termination != 0");
|
|
||||||
|
|
||||||
// Replies are generated inside
|
// Replies are generated inside
|
||||||
ExecuteHCICommandMessage(m_CtrlSetup);
|
ExecuteHCICommandMessage(*m_CtrlSetup);
|
||||||
|
m_CtrlSetup.reset();
|
||||||
|
send_reply = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case USBV0_IOCTL_BLKMSG:
|
case USBV0_IOCTL_BLKMSG:
|
||||||
{
|
{
|
||||||
const CtrlBuffer ctrl(CommandBuffer, _CommandAddress);
|
const CtrlBuffer ctrl{request};
|
||||||
switch (ctrl.m_endpoint)
|
switch (ctrl.m_endpoint)
|
||||||
{
|
{
|
||||||
case ACL_DATA_OUT: // ACL data is received from the stack
|
case ACL_DATA_OUT: // ACL data is received from the stack
|
||||||
{
|
{
|
||||||
// This is the ACL datapath from CPU to Wii Remote
|
// This is the ACL datapath from CPU to Wii Remote
|
||||||
// Here we only need to record the command address in case we need to delay the reply
|
|
||||||
m_ACLSetup = CommandBuffer.m_Address;
|
|
||||||
|
|
||||||
const auto* acl_header =
|
const auto* acl_header =
|
||||||
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.m_payload_addr));
|
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.m_payload_addr));
|
||||||
|
|
||||||
|
@ -216,69 +191,42 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtlV(u32 _CommandAdd
|
||||||
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
|
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
|
||||||
Memory::GetPointer(ctrl.m_payload_addr + sizeof(hci_acldata_hdr_t)),
|
Memory::GetPointer(ctrl.m_payload_addr + sizeof(hci_acldata_hdr_t)),
|
||||||
acl_header->length);
|
acl_header->length);
|
||||||
|
break;
|
||||||
_SendReply = true;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case ACL_DATA_IN: // We are given an ACL buffer to fill
|
case ACL_DATA_IN: // We are given an ACL buffer to fill
|
||||||
{
|
{
|
||||||
CtrlBuffer temp(CommandBuffer, _CommandAddress);
|
m_ACLEndpoint = std::make_unique<CtrlBuffer>(request);
|
||||||
m_ACLEndpoint = temp;
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address);
|
||||||
|
send_reply = false;
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL_DATA_IN: 0x%08x ", _CommandAddress);
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
|
||||||
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_BLKMSG: %x", ctrl.m_endpoint);
|
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_BLKMSG: %x", ctrl.m_endpoint);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case USBV0_IOCTL_INTRMSG:
|
case USBV0_IOCTL_INTRMSG:
|
||||||
{
|
{
|
||||||
const CtrlBuffer ctrl(CommandBuffer, _CommandAddress);
|
const CtrlBuffer ctrl{request};
|
||||||
if (ctrl.m_endpoint == HCI_EVENT) // We are given a HCI buffer to fill
|
if (ctrl.m_endpoint == HCI_EVENT) // We are given a HCI buffer to fill
|
||||||
{
|
{
|
||||||
CtrlBuffer temp(CommandBuffer, _CommandAddress);
|
m_HCIEndpoint = std::make_unique<CtrlBuffer>(request);
|
||||||
m_HCIEndpoint = temp;
|
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address);
|
||||||
|
send_reply = false;
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI_EVENT: 0x%08x ", _CommandAddress);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_INTRMSG: %x", ctrl.m_endpoint);
|
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_INTRMSG: %x", ctrl.m_endpoint);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_WIIMOTE);
|
||||||
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown CWII_IPC_HLE_Device_usb_oh1_57e_305: %x",
|
|
||||||
CommandBuffer.Parameter);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_WIIMOTE, "%s - IOCtlV:", GetDeviceName().c_str());
|
|
||||||
INFO_LOG(WII_IPC_WIIMOTE, " Parameter: 0x%x", CommandBuffer.Parameter);
|
|
||||||
INFO_LOG(WII_IPC_WIIMOTE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer);
|
|
||||||
INFO_LOG(WII_IPC_WIIMOTE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer);
|
|
||||||
INFO_LOG(WII_IPC_WIIMOTE, " BufferVector: 0x%08x", CommandBuffer.BufferVector);
|
|
||||||
INFO_LOG(WII_IPC_WIIMOTE, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address);
|
|
||||||
INFO_LOG(WII_IPC_WIIMOTE, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size);
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer,
|
|
||||||
CommandBuffer.NumberPayloadBuffer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write return value
|
return send_reply ? GetDefaultReply(IPC_SUCCESS) : GetNoReply();
|
||||||
Memory::Write_U32(0, _CommandAddress + 4);
|
|
||||||
return _SendReply ? GetDefaultReply() : GetNoReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we handle the USBV0_IOCTL_BLKMSG Ioctlv
|
// Here we handle the USBV0_IOCTL_BLKMSG Ioctlv
|
||||||
|
@ -306,22 +254,22 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendACLPacket(u16 connection_handl
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", connection_handle);
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", connection_handle);
|
||||||
|
|
||||||
if (m_ACLEndpoint.IsValid() && !m_HCIEndpoint.IsValid() && m_EventQueue.empty())
|
if (m_ACLEndpoint && !m_HCIEndpoint && m_EventQueue.empty())
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint valid, sending packet to %08x",
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint valid, sending packet to %08x",
|
||||||
m_ACLEndpoint.m_cmd_address);
|
m_ACLEndpoint->ios_request.address);
|
||||||
|
|
||||||
hci_acldata_hdr_t* header =
|
hci_acldata_hdr_t* header =
|
||||||
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint.m_payload_addr));
|
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint->m_payload_addr));
|
||||||
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||||
header->length = size;
|
header->length = size;
|
||||||
|
|
||||||
// Write the packet to the buffer
|
// Write the packet to the buffer
|
||||||
memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
|
memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
|
||||||
|
|
||||||
m_ACLEndpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
|
WII_IPC_HLE_Interface::EnqueueReply(m_ACLEndpoint->ios_request,
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_ACLEndpoint.m_cmd_address);
|
sizeof(hci_acldata_hdr_t) + size);
|
||||||
m_ACLEndpoint.Invalidate();
|
m_ACLEndpoint.reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -340,17 +288,16 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AddEventToQueue(const SQueuedEvent
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x completed...",
|
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x completed...",
|
||||||
((hci_event_hdr_t*)_event.m_buffer)->event);
|
((hci_event_hdr_t*)_event.m_buffer)->event);
|
||||||
|
|
||||||
if (m_HCIEndpoint.IsValid())
|
if (m_HCIEndpoint)
|
||||||
{
|
{
|
||||||
if (m_EventQueue.empty()) // fast path :)
|
if (m_EventQueue.empty()) // fast path :)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI endpoint valid, sending packet to %08x",
|
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI endpoint valid, sending packet to %08x",
|
||||||
m_HCIEndpoint.m_cmd_address);
|
m_HCIEndpoint->ios_request.address);
|
||||||
m_HCIEndpoint.FillBuffer(_event.m_buffer, _event.m_size);
|
m_HCIEndpoint->FillBuffer(_event.m_buffer, _event.m_size);
|
||||||
m_HCIEndpoint.SetRetVal(_event.m_size);
|
|
||||||
// Send a reply to indicate HCI buffer is filled
|
// Send a reply to indicate HCI buffer is filled
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint.m_cmd_address);
|
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint->ios_request, _event.m_size);
|
||||||
m_HCIEndpoint.Invalidate();
|
m_HCIEndpoint.reset();
|
||||||
}
|
}
|
||||||
else // push new one, pop oldest
|
else // push new one, pop oldest
|
||||||
{
|
{
|
||||||
|
@ -361,12 +308,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AddEventToQueue(const SQueuedEvent
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x "
|
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x "
|
||||||
"being written from queue (%zu) to %08x...",
|
"being written from queue (%zu) to %08x...",
|
||||||
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
|
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
|
||||||
m_HCIEndpoint.m_cmd_address);
|
m_HCIEndpoint->ios_request.address);
|
||||||
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
|
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
|
||||||
m_HCIEndpoint.SetRetVal(event.m_size);
|
|
||||||
// Send a reply to indicate HCI buffer is filled
|
// Send a reply to indicate HCI buffer is filled
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint.m_cmd_address);
|
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint->ios_request, event.m_size);
|
||||||
m_HCIEndpoint.Invalidate();
|
m_HCIEndpoint.reset();
|
||||||
m_EventQueue.pop_front();
|
m_EventQueue.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,24 +327,26 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AddEventToQueue(const SQueuedEvent
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
|
||||||
{
|
{
|
||||||
// check HCI queue
|
// check HCI queue
|
||||||
if (!m_EventQueue.empty() && m_HCIEndpoint.IsValid())
|
if (!m_EventQueue.empty() && m_HCIEndpoint)
|
||||||
{
|
{
|
||||||
// an endpoint has become available, and we have a stored response.
|
// an endpoint has become available, and we have a stored response.
|
||||||
const SQueuedEvent& event = m_EventQueue.front();
|
const SQueuedEvent& event = m_EventQueue.front();
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x being written from queue (%zu) to %08x...",
|
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x being written from queue (%zu) to %08x...",
|
||||||
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
|
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
|
||||||
m_HCIEndpoint.m_cmd_address);
|
m_HCIEndpoint->ios_request.address);
|
||||||
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
|
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
|
||||||
m_HCIEndpoint.SetRetVal(event.m_size);
|
|
||||||
// Send a reply to indicate HCI buffer is filled
|
// Send a reply to indicate HCI buffer is filled
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint.m_cmd_address);
|
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint->ios_request, event.m_size);
|
||||||
m_HCIEndpoint.Invalidate();
|
m_HCIEndpoint.reset();
|
||||||
m_EventQueue.pop_front();
|
m_EventQueue.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check ACL queue
|
// check ACL queue
|
||||||
if (!m_acl_pool.IsEmpty() && m_ACLEndpoint.IsValid() && m_EventQueue.empty())
|
if (!m_acl_pool.IsEmpty() && m_ACLEndpoint && m_EventQueue.empty())
|
||||||
m_acl_pool.WriteToEndpoint(m_ACLEndpoint);
|
{
|
||||||
|
m_acl_pool.WriteToEndpoint(*m_ACLEndpoint);
|
||||||
|
m_ACLEndpoint.reset();
|
||||||
|
}
|
||||||
|
|
||||||
// We wait for ScanEnable to be sent from the Bluetooth stack through HCI_CMD_WRITE_SCAN_ENABLE
|
// We wait for ScanEnable to be sent from the Bluetooth stack through HCI_CMD_WRITE_SCAN_ENABLE
|
||||||
// before we initiate the connection.
|
// before we initiate the connection.
|
||||||
|
@ -406,7 +354,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
|
||||||
// FiRES: TODO find a better way to do this
|
// FiRES: TODO find a better way to do this
|
||||||
|
|
||||||
// Create ACL connection
|
// Create ACL connection
|
||||||
if (m_HCIEndpoint.IsValid() && (m_ScanEnable & HCI_PAGE_SCAN_ENABLE))
|
if (m_HCIEndpoint && (m_ScanEnable & HCI_PAGE_SCAN_ENABLE))
|
||||||
{
|
{
|
||||||
for (auto& wiimote : m_WiiMotes)
|
for (auto& wiimote : m_WiiMotes)
|
||||||
{
|
{
|
||||||
|
@ -419,7 +367,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link channels when connected
|
// Link channels when connected
|
||||||
if (m_ACLEndpoint.IsValid())
|
if (m_ACLEndpoint)
|
||||||
{
|
{
|
||||||
for (auto& wiimote : m_WiiMotes)
|
for (auto& wiimote : m_WiiMotes)
|
||||||
{
|
{
|
||||||
|
@ -473,7 +421,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ACLPool::WriteToEndpoint(CtrlBuffe
|
||||||
|
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
|
||||||
"queue to %08x",
|
"queue to %08x",
|
||||||
endpoint.m_cmd_address);
|
endpoint.ios_request.address);
|
||||||
|
|
||||||
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_payload_addr);
|
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_payload_addr);
|
||||||
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||||
|
@ -482,12 +430,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ACLPool::WriteToEndpoint(CtrlBuffe
|
||||||
// Write the packet to the buffer
|
// Write the packet to the buffer
|
||||||
std::copy(data, data + size, (u8*)pHeader + sizeof(hci_acldata_hdr_t));
|
std::copy(data, data + size, (u8*)pHeader + sizeof(hci_acldata_hdr_t));
|
||||||
|
|
||||||
endpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
|
|
||||||
|
|
||||||
m_queue.pop_front();
|
m_queue.pop_front();
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(endpoint.m_cmd_address);
|
WII_IPC_HLE_Interface::EnqueueReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size);
|
||||||
endpoint.Invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventInquiryComplete()
|
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventInquiryComplete()
|
||||||
|
@ -1027,10 +972,10 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventConPacketTypeChange(u16 _
|
||||||
// Command dispatcher
|
// Command dispatcher
|
||||||
// This is called from the USBV0_IOCTL_CTRLMSG Ioctlv
|
// This is called from the USBV0_IOCTL_CTRLMSG Ioctlv
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
|
||||||
const SHCICommandMessage& _rHCICommandMessage)
|
const CtrlMessage& ctrl_message)
|
||||||
{
|
{
|
||||||
u8* pInput = Memory::GetPointer(_rHCICommandMessage.m_PayLoadAddr + 3);
|
u8* pInput = Memory::GetPointer(ctrl_message.payload_addr + 3);
|
||||||
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(_rHCICommandMessage.m_PayLoadAddr);
|
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(ctrl_message.payload_addr);
|
||||||
|
|
||||||
u16 ocf = HCI_OCF(pMsg->Opcode);
|
u16 ocf = HCI_OCF(pMsg->Opcode);
|
||||||
u16 ogf = HCI_OGF(pMsg->Opcode);
|
u16 ogf = HCI_OGF(pMsg->Opcode);
|
||||||
|
@ -1114,11 +1059,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
|
||||||
|
|
||||||
// vendor specific...
|
// vendor specific...
|
||||||
case 0xFC4C:
|
case 0xFC4C:
|
||||||
CommandVendorSpecific_FC4C(pInput, _rHCICommandMessage.m_PayLoadSize - 3);
|
CommandVendorSpecific_FC4C(pInput, ctrl_message.length - 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFC4F:
|
case 0xFC4F:
|
||||||
CommandVendorSpecific_FC4F(pInput, _rHCICommandMessage.m_PayLoadSize - 3);
|
CommandVendorSpecific_FC4F(pInput, ctrl_message.length - 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HCI_CMD_INQUIRY_CANCEL:
|
case HCI_CMD_INQUIRY_CANCEL:
|
||||||
|
@ -1207,7 +1152,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
// HCI command is finished, send a reply to command
|
// HCI command is finished, send a reply to command
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(_rHCICommandMessage.m_Address);
|
WII_IPC_HLE_Interface::EnqueueReply(ctrl_message.ios_request, ctrl_message.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -43,10 +44,8 @@ public:
|
||||||
|
|
||||||
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_emu();
|
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_emu();
|
||||||
|
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
|
void Close() override;
|
||||||
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
|
||||||
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
|
@ -62,31 +61,16 @@ public:
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SHCICommandMessage
|
|
||||||
{
|
|
||||||
u8 bRequestType;
|
|
||||||
u8 bRequest;
|
|
||||||
u16 wValue;
|
|
||||||
u16 wIndex;
|
|
||||||
u16 wLength;
|
|
||||||
|
|
||||||
u32 m_PayLoadAddr;
|
|
||||||
u32 m_PayLoadSize;
|
|
||||||
u32 m_Address;
|
|
||||||
};
|
|
||||||
|
|
||||||
bdaddr_t m_ControllerBD;
|
bdaddr_t m_ControllerBD;
|
||||||
|
|
||||||
// this is used to trigger connecting via ACL
|
// this is used to trigger connecting via ACL
|
||||||
u8 m_ScanEnable = 0;
|
u8 m_ScanEnable = 0;
|
||||||
|
|
||||||
SHCICommandMessage m_CtrlSetup;
|
std::unique_ptr<CtrlMessage> m_CtrlSetup;
|
||||||
CtrlBuffer m_HCIEndpoint;
|
std::unique_ptr<CtrlBuffer> m_HCIEndpoint;
|
||||||
|
std::unique_ptr<CtrlBuffer> m_ACLEndpoint;
|
||||||
std::deque<SQueuedEvent> m_EventQueue;
|
std::deque<SQueuedEvent> m_EventQueue;
|
||||||
|
|
||||||
u32 m_ACLSetup;
|
|
||||||
CtrlBuffer m_ACLEndpoint;
|
|
||||||
|
|
||||||
class ACLPool
|
class ACLPool
|
||||||
{
|
{
|
||||||
struct Packet
|
struct Packet
|
||||||
|
@ -109,7 +93,7 @@ private:
|
||||||
void DoState(PointerWrap& p) { p.Do(m_queue); }
|
void DoState(PointerWrap& p) { p.Do(m_queue); }
|
||||||
} m_acl_pool;
|
} m_acl_pool;
|
||||||
|
|
||||||
u32 m_PacketCount[MAX_BBMOTES];
|
u32 m_PacketCount[MAX_BBMOTES] = {};
|
||||||
u64 m_last_ticks = 0;
|
u64 m_last_ticks = 0;
|
||||||
|
|
||||||
// Send ACL data to a device (wiimote)
|
// Send ACL data to a device (wiimote)
|
||||||
|
@ -138,7 +122,7 @@ private:
|
||||||
bool SendEventLinkKeyNotification(const u8 num_to_send);
|
bool SendEventLinkKeyNotification(const u8 num_to_send);
|
||||||
|
|
||||||
// Execute HCI Message
|
// Execute HCI Message
|
||||||
void ExecuteHCICommandMessage(const SHCICommandMessage& _rCtrlMessage);
|
void ExecuteHCICommandMessage(const CtrlMessage& ctrl_message);
|
||||||
|
|
||||||
// OGF 0x01 - Link control commands and return parameters
|
// OGF 0x01 - Link control commands and return parameters
|
||||||
void CommandWriteInquiryMode(const u8* input);
|
void CommandWriteInquiryMode(const u8* input);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
|
#include "Common/CommonFuncs.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/Network.h"
|
#include "Common/Network.h"
|
||||||
|
@ -89,7 +90,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305_real::~CWII_IPC_HLE_Device_usb_oh1_57e_305_r
|
||||||
SaveLinkKeys();
|
SaveLinkKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Open(u32 command_address, u32 mode)
|
IOSReturnCode CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
libusb_device** list;
|
libusb_device** list;
|
||||||
const ssize_t cnt = libusb_get_device_list(m_libusb_context, &list);
|
const ssize_t cnt = libusb_get_device_list(m_libusb_context, &list);
|
||||||
|
@ -136,18 +137,18 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Open(u32 command_addr
|
||||||
PanicAlertT("Bluetooth passthrough mode is enabled, "
|
PanicAlertT("Bluetooth passthrough mode is enabled, "
|
||||||
"but no usable Bluetooth USB device was found. Aborting.");
|
"but no usable Bluetooth USB device was found. Aborting.");
|
||||||
Core::QueueHostJob(Core::Stop);
|
Core::QueueHostJob(Core::Stop);
|
||||||
return GetNoReply();
|
return IPC_ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
StartTransferThread();
|
StartTransferThread();
|
||||||
|
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetDefaultReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Close(u32 command_address, bool force)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Close()
|
||||||
{
|
{
|
||||||
if (!force)
|
if (m_handle)
|
||||||
{
|
{
|
||||||
libusb_release_interface(m_handle, 0);
|
libusb_release_interface(m_handle, 0);
|
||||||
StopTransferThread();
|
StopTransferThread();
|
||||||
|
@ -156,10 +157,9 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Close(u32 command_add
|
||||||
}
|
}
|
||||||
|
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_address)
|
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
if (!m_is_wii_bt_module && s_need_reset_keys.TestAndClear())
|
if (!m_is_wii_bt_module && s_need_reset_keys.TestAndClear())
|
||||||
{
|
{
|
||||||
|
@ -170,14 +170,13 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
|
||||||
WaitForHCICommandComplete(HCI_CMD_WRITE_STORED_LINK_KEY);
|
WaitForHCICommandComplete(HCI_CMD_WRITE_STORED_LINK_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SIOCtlVBuffer cmd_buffer(command_address);
|
switch (request.request)
|
||||||
switch (cmd_buffer.Parameter)
|
|
||||||
{
|
{
|
||||||
// HCI commands to the Bluetooth adapter
|
// HCI commands to the Bluetooth adapter
|
||||||
case USBV0_IOCTL_CTRLMSG:
|
case USBV0_IOCTL_CTRLMSG:
|
||||||
{
|
{
|
||||||
auto cmd = std::make_unique<CtrlMessage>(cmd_buffer);
|
auto cmd = std::make_unique<CtrlMessage>(request);
|
||||||
const u16 opcode = *reinterpret_cast<u16*>(Memory::GetPointer(cmd->payload_addr));
|
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->payload_addr));
|
||||||
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
|
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
m_fake_read_buffer_size_reply.Set();
|
m_fake_read_buffer_size_reply.Set();
|
||||||
|
@ -220,25 +219,24 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
|
||||||
case USBV0_IOCTL_BLKMSG:
|
case USBV0_IOCTL_BLKMSG:
|
||||||
case USBV0_IOCTL_INTRMSG:
|
case USBV0_IOCTL_INTRMSG:
|
||||||
{
|
{
|
||||||
auto buffer = std::make_unique<CtrlBuffer>(cmd_buffer, command_address);
|
auto buffer = std::make_unique<CtrlBuffer>(request);
|
||||||
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG && m_fake_read_buffer_size_reply.TestAndClear())
|
if (request.request == USBV0_IOCTL_INTRMSG && m_fake_read_buffer_size_reply.TestAndClear())
|
||||||
{
|
{
|
||||||
FakeReadBufferSizeReply(*buffer);
|
FakeReadBufferSizeReply(*buffer);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG && m_fake_vendor_command_reply.TestAndClear())
|
if (request.request == USBV0_IOCTL_INTRMSG && m_fake_vendor_command_reply.TestAndClear())
|
||||||
{
|
{
|
||||||
FakeVendorCommandReply(*buffer);
|
FakeVendorCommandReply(*buffer);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG &&
|
if (request.request == USBV0_IOCTL_INTRMSG && m_sync_button_state == SyncButtonState::Pressed)
|
||||||
m_sync_button_state == SyncButtonState::Pressed)
|
|
||||||
{
|
{
|
||||||
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
|
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
|
||||||
FakeSyncButtonPressedEvent(*buffer);
|
FakeSyncButtonPressedEvent(*buffer);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG &&
|
if (request.request == USBV0_IOCTL_INTRMSG &&
|
||||||
m_sync_button_state == SyncButtonState::LongPressed)
|
m_sync_button_state == SyncButtonState::LongPressed)
|
||||||
{
|
{
|
||||||
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
|
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
|
||||||
|
@ -253,8 +251,8 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
|
||||||
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||||
transfer->length = buffer->m_length;
|
transfer->length = buffer->m_length;
|
||||||
transfer->timeout = TIMEOUT;
|
transfer->timeout = TIMEOUT;
|
||||||
transfer->type = cmd_buffer.Parameter == USBV0_IOCTL_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
|
transfer->type = request.request == USBV0_IOCTL_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
|
||||||
LIBUSB_TRANSFER_TYPE_INTERRUPT;
|
LIBUSB_TRANSFER_TYPE_INTERRUPT;
|
||||||
transfer->user_data = buffer.release();
|
transfer->user_data = buffer.release();
|
||||||
libusb_submit_transfer(transfer);
|
libusb_submit_transfer(transfer);
|
||||||
break;
|
break;
|
||||||
|
@ -387,7 +385,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305_real::SendHCIStoreLinkKeyCommand()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(const CtrlBuffer& ctrl)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(CtrlBuffer& ctrl)
|
||||||
{
|
{
|
||||||
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
||||||
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
|
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
|
||||||
|
@ -395,8 +393,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(const Ctrl
|
||||||
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2;
|
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2;
|
||||||
hci_event->PacketIndicator = 0x01;
|
hci_event->PacketIndicator = 0x01;
|
||||||
hci_event->Opcode = m_fake_vendor_command_reply_opcode;
|
hci_event->Opcode = m_fake_vendor_command_reply_opcode;
|
||||||
ctrl.SetRetVal(sizeof(SHCIEventCommand));
|
WII_IPC_HLE_Interface::EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(SHCIEventCommand)));
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(ctrl.m_cmd_address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Due to how the widcomm stack which Nintendo uses is coded, we must never
|
// Due to how the widcomm stack which Nintendo uses is coded, we must never
|
||||||
|
@ -404,7 +401,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(const Ctrl
|
||||||
// - it will cause a u8 underflow and royally screw things up.
|
// - it will cause a u8 underflow and royally screw things up.
|
||||||
// Therefore, the reply to this command has to be faked to avoid random, weird issues
|
// Therefore, the reply to this command has to be faked to avoid random, weird issues
|
||||||
// (including Wiimote disconnects and "event mismatch" warning messages).
|
// (including Wiimote disconnects and "event mismatch" warning messages).
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeReadBufferSizeReply(const CtrlBuffer& ctrl)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeReadBufferSizeReply(CtrlBuffer& ctrl)
|
||||||
{
|
{
|
||||||
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
||||||
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
|
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
|
||||||
|
@ -421,11 +418,12 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeReadBufferSizeReply(const Ctr
|
||||||
reply.num_sco_pkts = SCO_PKT_NUM;
|
reply.num_sco_pkts = SCO_PKT_NUM;
|
||||||
|
|
||||||
memcpy(packet + sizeof(SHCIEventCommand), &reply, sizeof(hci_read_buffer_size_rp));
|
memcpy(packet + sizeof(SHCIEventCommand), &reply, sizeof(hci_read_buffer_size_rp));
|
||||||
ctrl.SetRetVal(sizeof(SHCIEventCommand) + sizeof(hci_read_buffer_size_rp));
|
WII_IPC_HLE_Interface::EnqueueReply(
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(ctrl.m_cmd_address);
|
ctrl.ios_request,
|
||||||
|
static_cast<s32>(sizeof(SHCIEventCommand) + sizeof(hci_read_buffer_size_rp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonEvent(const CtrlBuffer& ctrl,
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonEvent(CtrlBuffer& ctrl,
|
||||||
const u8* payload, const u8 size)
|
const u8* payload, const u8 size)
|
||||||
{
|
{
|
||||||
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
||||||
|
@ -433,15 +431,15 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonEvent(const CtrlBuf
|
||||||
hci_event->event = HCI_EVENT_VENDOR;
|
hci_event->event = HCI_EVENT_VENDOR;
|
||||||
hci_event->length = size;
|
hci_event->length = size;
|
||||||
memcpy(packet + sizeof(hci_event_hdr_t), payload, size);
|
memcpy(packet + sizeof(hci_event_hdr_t), payload, size);
|
||||||
ctrl.SetRetVal(sizeof(hci_event_hdr_t) + size);
|
WII_IPC_HLE_Interface::EnqueueReply(ctrl.ios_request,
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(ctrl.m_cmd_address);
|
static_cast<s32>(sizeof(hci_event_hdr_t) + size));
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the red sync button is pressed, a HCI event is generated:
|
// When the red sync button is pressed, a HCI event is generated:
|
||||||
// > HCI Event: Vendor (0xff) plen 1
|
// > HCI Event: Vendor (0xff) plen 1
|
||||||
// 08
|
// 08
|
||||||
// This causes the emulated software to perform a BT inquiry and connect to found Wiimotes.
|
// This causes the emulated software to perform a BT inquiry and connect to found Wiimotes.
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(CtrlBuffer& ctrl)
|
||||||
{
|
{
|
||||||
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button pressed' (0x08) event packet");
|
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button pressed' (0x08) event packet");
|
||||||
const u8 payload[1] = {0x08};
|
const u8 payload[1] = {0x08};
|
||||||
|
@ -450,7 +448,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(const
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the red sync button is held for 10 seconds, a HCI event with payload 09 is sent.
|
// When the red sync button is held for 10 seconds, a HCI event with payload 09 is sent.
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonHeldEvent(CtrlBuffer& ctrl)
|
||||||
{
|
{
|
||||||
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
|
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
|
||||||
const u8 payload[1] = {0x09};
|
const u8 payload[1] = {0x09};
|
||||||
|
@ -580,7 +578,8 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::CommandCallback(libusb_transfer*
|
||||||
s_showed_failed_transfer.Clear();
|
s_showed_failed_transfer.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(cmd->address, 0, CoreTiming::FromThread::NON_CPU);
|
WII_IPC_HLE_Interface::EnqueueReply(cmd->ios_request, tr->actual_length, 0,
|
||||||
|
CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferCallback(libusb_transfer* tr)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferCallback(libusb_transfer* tr)
|
||||||
|
@ -624,6 +623,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferCallback(libusb_transfer*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl->SetRetVal(tr->actual_length);
|
WII_IPC_HLE_Interface::EnqueueReply(ctrl->ios_request, tr->actual_length, 0,
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(ctrl->m_cmd_address, 0, CoreTiming::FromThread::NON_CPU);
|
CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,9 @@ public:
|
||||||
CWII_IPC_HLE_Device_usb_oh1_57e_305_real(u32 device_id, const std::string& device_name);
|
CWII_IPC_HLE_Device_usb_oh1_57e_305_real(u32 device_id, const std::string& device_name);
|
||||||
~CWII_IPC_HLE_Device_usb_oh1_57e_305_real() override;
|
~CWII_IPC_HLE_Device_usb_oh1_57e_305_real() override;
|
||||||
|
|
||||||
IPCCommandResult Open(u32 command_address, u32 mode) override;
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Close(u32 command_address, bool force) override;
|
void Close() override;
|
||||||
IPCCommandResult IOCtlV(u32 command_address) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
void UpdateSyncButtonState(bool is_held) override;
|
void UpdateSyncButtonState(bool is_held) override;
|
||||||
|
@ -80,11 +80,11 @@ private:
|
||||||
void SendHCIResetCommand();
|
void SendHCIResetCommand();
|
||||||
void SendHCIDeleteLinkKeyCommand();
|
void SendHCIDeleteLinkKeyCommand();
|
||||||
bool SendHCIStoreLinkKeyCommand();
|
bool SendHCIStoreLinkKeyCommand();
|
||||||
void FakeVendorCommandReply(const CtrlBuffer& ctrl);
|
void FakeVendorCommandReply(CtrlBuffer& ctrl);
|
||||||
void FakeReadBufferSizeReply(const CtrlBuffer& ctrl);
|
void FakeReadBufferSizeReply(CtrlBuffer& ctrl);
|
||||||
void FakeSyncButtonEvent(const CtrlBuffer& ctrl, const u8* payload, u8 size);
|
void FakeSyncButtonEvent(CtrlBuffer& ctrl, const u8* payload, u8 size);
|
||||||
void FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl);
|
void FakeSyncButtonPressedEvent(CtrlBuffer& ctrl);
|
||||||
void FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl);
|
void FakeSyncButtonHeldEvent(CtrlBuffer& ctrl);
|
||||||
|
|
||||||
void LoadLinkKeys();
|
void LoadLinkKeys();
|
||||||
void SaveLinkKeys();
|
void SaveLinkKeys();
|
||||||
|
|
|
@ -12,11 +12,11 @@ namespace Core
|
||||||
void DisplayMessage(const std::string& message, int time_in_ms);
|
void DisplayMessage(const std::string& message, int time_in_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::Open(u32 command_address, u32 mode)
|
IOSReturnCode CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
PanicAlertT("Bluetooth passthrough mode is enabled, but Dolphin was built without libusb."
|
PanicAlertT("Bluetooth passthrough mode is enabled, but Dolphin was built without libusb."
|
||||||
" Passthrough mode cannot be used.");
|
" Passthrough mode cannot be used.");
|
||||||
return GetNoReply();
|
return IPC_ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::DoState(PointerWrap& p)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::DoState(PointerWrap& p)
|
||||||
|
|
|
@ -16,11 +16,10 @@ class CWII_IPC_HLE_Device_usb_oh1_57e_305_stub final
|
||||||
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
|
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_usb_oh1_57e_305_stub(u32 device_id, const std::string& device_name)
|
CWII_IPC_HLE_Device_usb_oh1_57e_305_stub(const u32 device_id, const std::string& device_name)
|
||||||
: CWII_IPC_HLE_Device_usb_oh1_57e_305_base(device_id, device_name)
|
: CWII_IPC_HLE_Device_usb_oh1_57e_305_base(device_id, device_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~CWII_IPC_HLE_Device_usb_oh1_57e_305_stub() override {}
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Open(u32 command_address, u32 mode) override;
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,17 +38,14 @@ CWII_IPC_HLE_Device_usb_kbd::CWII_IPC_HLE_Device_usb_kbd(u32 _DeviceID,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_usb_kbd::~CWII_IPC_HLE_Device_usb_kbd()
|
IOSReturnCode CWII_IPC_HLE_Device_usb_kbd::Open(const IOSOpenRequest& request)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_kbd::Open(u32 _CommandAddress, u32 _Mode)
|
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_HLE, "CWII_IPC_HLE_Device_usb_kbd: Open");
|
INFO_LOG(WII_IPC_HLE, "CWII_IPC_HLE_Device_usb_kbd: Open");
|
||||||
IniFile ini;
|
IniFile ini;
|
||||||
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||||
ini.GetOrCreateSection("USB Keyboard")->Get("Layout", &m_KeyboardLayout, KBD_LAYOUT_QWERTY);
|
ini.GetOrCreateSection("USB Keyboard")->Get("Layout", &m_KeyboardLayout, KBD_LAYOUT_QWERTY);
|
||||||
|
|
||||||
|
m_MessageQueue = std::queue<SMessageData>();
|
||||||
for (bool& pressed : m_OldKeyBuffer)
|
for (bool& pressed : m_OldKeyBuffer)
|
||||||
{
|
{
|
||||||
pressed = false;
|
pressed = false;
|
||||||
|
@ -58,39 +55,17 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_kbd::Open(u32 _CommandAddress, u32 _Mod
|
||||||
|
|
||||||
// m_MessageQueue.push(SMessageData(MSG_KBD_CONNECT, 0, nullptr));
|
// m_MessageQueue.push(SMessageData(MSG_KBD_CONNECT, 0, nullptr));
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetDefaultReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_kbd::Close(u32 _CommandAddress, bool _bForce)
|
IPCCommandResult CWII_IPC_HLE_Device_usb_kbd::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_HLE, "CWII_IPC_HLE_Device_usb_kbd: Close");
|
|
||||||
while (!m_MessageQueue.empty())
|
|
||||||
m_MessageQueue.pop();
|
|
||||||
m_is_active = false;
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_kbd::Write(u32 _CommandAddress)
|
|
||||||
{
|
|
||||||
DEBUG_LOG(WII_IPC_HLE, "Ignoring write to CWII_IPC_HLE_Device_usb_kbd");
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
DumpCommands(_CommandAddress, 10, LogTypes::WII_IPC_HLE, LogTypes::LDEBUG);
|
|
||||||
#endif
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_kbd::IOCtl(u32 _CommandAddress)
|
|
||||||
{
|
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
|
||||||
|
|
||||||
if (SConfig::GetInstance().m_WiiKeyboard && !Core::g_want_determinism && !m_MessageQueue.empty())
|
if (SConfig::GetInstance().m_WiiKeyboard && !Core::g_want_determinism && !m_MessageQueue.empty())
|
||||||
{
|
{
|
||||||
Memory::CopyToEmu(BufferOut, &m_MessageQueue.front(), sizeof(SMessageData));
|
Memory::CopyToEmu(request.buffer_out, &m_MessageQueue.front(), sizeof(SMessageData));
|
||||||
m_MessageQueue.pop();
|
m_MessageQueue.pop();
|
||||||
}
|
}
|
||||||
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_usb_kbd::IsKeyPressed(int _Key)
|
bool CWII_IPC_HLE_Device_usb_kbd::IsKeyPressed(int _Key)
|
||||||
|
|
|
@ -15,12 +15,9 @@ class CWII_IPC_HLE_Device_usb_kbd : public IWII_IPC_HLE_Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_usb_kbd(u32 _DeviceID, const std::string& _rDeviceName);
|
CWII_IPC_HLE_Device_usb_kbd(u32 _DeviceID, const std::string& _rDeviceName);
|
||||||
virtual ~CWII_IPC_HLE_Device_usb_kbd();
|
|
||||||
|
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult Write(u32 _CommandAddress) override;
|
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -12,43 +12,22 @@ CWII_IPC_HLE_Device_usb_ven::CWII_IPC_HLE_Device_usb_ven(const u32 device_id,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_usb_ven::~CWII_IPC_HLE_Device_usb_ven()
|
IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
}
|
request.Dump(GetDeviceName());
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtlV(u32 command_address)
|
|
||||||
{
|
|
||||||
SIOCtlVBuffer command_buffer(command_address);
|
|
||||||
|
|
||||||
INFO_LOG(OSHLE, "%s - IOCtlV:", GetDeviceName().c_str());
|
|
||||||
INFO_LOG(OSHLE, " Parameter: 0x%x", command_buffer.Parameter);
|
|
||||||
INFO_LOG(OSHLE, " NumberIn: 0x%08x", command_buffer.NumberInBuffer);
|
|
||||||
INFO_LOG(OSHLE, " NumberOut: 0x%08x", command_buffer.NumberPayloadBuffer);
|
|
||||||
INFO_LOG(OSHLE, " BufferVector: 0x%08x", command_buffer.BufferVector);
|
|
||||||
DumpAsync(command_buffer.BufferVector, command_buffer.NumberInBuffer,
|
|
||||||
command_buffer.NumberPayloadBuffer);
|
|
||||||
|
|
||||||
Memory::Write_U32(0, command_address + 4);
|
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtl(u32 command_address)
|
IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
IPCCommandResult reply = GetDefaultReply();
|
request.Log(GetDeviceName(), LogTypes::OSHLE);
|
||||||
u32 command = Memory::Read_U32(command_address + 0x0c);
|
|
||||||
u32 buffer_in = Memory::Read_U32(command_address + 0x10);
|
|
||||||
u32 buffer_in_size = Memory::Read_U32(command_address + 0x14);
|
|
||||||
u32 buffer_out = Memory::Read_U32(command_address + 0x18);
|
|
||||||
u32 buffer_out_size = Memory::Read_U32(command_address + 0x1c);
|
|
||||||
|
|
||||||
INFO_LOG(OSHLE, "%s - IOCtl: %x", GetDeviceName().c_str(), command);
|
IPCCommandResult reply = GetDefaultReply(IPC_SUCCESS);
|
||||||
INFO_LOG(OSHLE, "%x:%x %x:%x", buffer_in, buffer_in_size, buffer_out, buffer_out_size);
|
switch (request.request)
|
||||||
|
|
||||||
switch (command)
|
|
||||||
{
|
{
|
||||||
case USBV5_IOCTL_GETVERSION:
|
case USBV5_IOCTL_GETVERSION:
|
||||||
Memory::Write_U32(0x50001, buffer_out);
|
Memory::Write_U32(0x50001, request.buffer_out);
|
||||||
reply = GetDefaultReply();
|
reply = GetDefaultReply(IPC_SUCCESS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USBV5_IOCTL_GETDEVICECHANGE:
|
case USBV5_IOCTL_GETDEVICECHANGE:
|
||||||
|
@ -57,48 +36,41 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtl(u32 command_address)
|
||||||
static bool firstcall = true;
|
static bool firstcall = true;
|
||||||
if (firstcall)
|
if (firstcall)
|
||||||
{
|
{
|
||||||
reply = GetDefaultReply();
|
reply = GetDefaultReply(IPC_SUCCESS);
|
||||||
firstcall = false;
|
firstcall = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// num devices
|
// num devices
|
||||||
Memory::Write_U32(0, command_address + 4);
|
reply = GetDefaultReply(0);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USBV5_IOCTL_ATTACHFINISH:
|
case USBV5_IOCTL_ATTACHFINISH:
|
||||||
reply = GetDefaultReply();
|
reply = GetDefaultReply(IPC_SUCCESS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USBV5_IOCTL_SUSPEND_RESUME:
|
case USBV5_IOCTL_SUSPEND_RESUME:
|
||||||
DEBUG_LOG(OSHLE, "Device: %i Resumed: %i", Memory::Read_U32(buffer_in),
|
DEBUG_LOG(OSHLE, "Device: %i Resumed: %i", Memory::Read_U32(request.buffer_in),
|
||||||
Memory::Read_U32(buffer_in + 4));
|
Memory::Read_U32(request.buffer_in + 4));
|
||||||
reply = GetDefaultReply();
|
reply = GetDefaultReply(IPC_SUCCESS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USBV5_IOCTL_GETDEVPARAMS:
|
case USBV5_IOCTL_GETDEVPARAMS:
|
||||||
{
|
{
|
||||||
s32 device = Memory::Read_U32(buffer_in);
|
s32 device = Memory::Read_U32(request.buffer_in);
|
||||||
u32 unk = Memory::Read_U32(buffer_in + 4);
|
u32 unk = Memory::Read_U32(request.buffer_in + 4);
|
||||||
|
|
||||||
DEBUG_LOG(OSHLE, "USBV5_IOCTL_GETDEVPARAMS device: %i unk: %i", device, unk);
|
DEBUG_LOG(OSHLE, "USBV5_IOCTL_GETDEVPARAMS device: %i unk: %i", device, unk);
|
||||||
|
|
||||||
Memory::Write_U32(0, buffer_out);
|
Memory::Write_U32(0, request.buffer_out);
|
||||||
|
|
||||||
reply = GetDefaultReply();
|
reply = GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_LOG(OSHLE, "%x:%x %x:%x", buffer_in, buffer_in_size, buffer_out, buffer_out_size);
|
request.Log(GetDeviceName(), LogTypes::OSHLE, LogTypes::LDEBUG);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(0, command_address + 4);
|
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_ven::DoState(PointerWrap& p)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,19 +10,13 @@
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
|
||||||
|
|
||||||
class PointerWrap;
|
|
||||||
|
|
||||||
class CWII_IPC_HLE_Device_usb_ven final : public IWII_IPC_HLE_Device
|
class CWII_IPC_HLE_Device_usb_ven final : public IWII_IPC_HLE_Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_usb_ven(u32 device_id, const std::string& device_name);
|
CWII_IPC_HLE_Device_usb_ven(u32 device_id, const std::string& device_name);
|
||||||
|
|
||||||
~CWII_IPC_HLE_Device_usb_ven() override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 command_address) override;
|
|
||||||
IPCCommandResult IOCtl(u32 command_address) override;
|
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum USBIOCtl
|
enum USBIOCtl
|
||||||
|
|
|
@ -29,17 +29,11 @@ CWII_IPC_HLE_Device_usb_wfssrv::CWII_IPC_HLE_Device_usb_wfssrv(u32 device_id,
|
||||||
m_device_name = "msc01";
|
m_device_name = "msc01";
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::IOCtl(u32 command_address)
|
IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
u32 command = Memory::Read_U32(command_address + 0xC);
|
|
||||||
u32 buffer_in = Memory::Read_U32(command_address + 0x10);
|
|
||||||
u32 buffer_in_size = Memory::Read_U32(command_address + 0x14);
|
|
||||||
u32 buffer_out = Memory::Read_U32(command_address + 0x18);
|
|
||||||
u32 buffer_out_size = Memory::Read_U32(command_address + 0x1C);
|
|
||||||
|
|
||||||
int return_error_code = IPC_SUCCESS;
|
int return_error_code = IPC_SUCCESS;
|
||||||
|
|
||||||
switch (command)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
case IOCTL_WFS_INIT:
|
case IOCTL_WFS_INIT:
|
||||||
// TODO(wfs): Implement.
|
// TODO(wfs): Implement.
|
||||||
|
@ -48,56 +42,56 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::IOCtl(u32 command_address)
|
||||||
|
|
||||||
case IOCTL_WFS_DEVICE_INFO:
|
case IOCTL_WFS_DEVICE_INFO:
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_DEVICE_INFO");
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_DEVICE_INFO");
|
||||||
Memory::Write_U64(16ull << 30, buffer_out); // 16GB storage.
|
Memory::Write_U64(16ull << 30, request.buffer_out); // 16GB storage.
|
||||||
Memory::Write_U8(4, buffer_out + 8);
|
Memory::Write_U8(4, request.buffer_out + 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFS_GET_DEVICE_NAME:
|
case IOCTL_WFS_GET_DEVICE_NAME:
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GET_DEVICE_NAME");
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GET_DEVICE_NAME");
|
||||||
Memory::Write_U8(static_cast<u8>(m_device_name.size()), buffer_out);
|
Memory::Write_U8(static_cast<u8>(m_device_name.size()), request.buffer_out);
|
||||||
Memory::CopyToEmu(buffer_out + 1, m_device_name.data(), m_device_name.size());
|
Memory::CopyToEmu(request.buffer_out + 1, m_device_name.data(), m_device_name.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IOCTL_WFS_ATTACH_DETACH_2:
|
case IOCTL_WFS_ATTACH_DETACH_2:
|
||||||
// TODO(wfs): Implement.
|
// TODO(wfs): Implement.
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_ATTACH_DETACH_2(%d)", command);
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_ATTACH_DETACH_2(%u)", request.request);
|
||||||
Memory::Write_U32(1, buffer_out);
|
Memory::Write_U32(1, request.buffer_out);
|
||||||
Memory::Write_U32(0, buffer_out + 4); // device id?
|
Memory::Write_U32(0, request.buffer_out + 4); // device id?
|
||||||
Memory::Write_U32(0, buffer_out + 8);
|
Memory::Write_U32(0, request.buffer_out + 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFS_ATTACH_DETACH:
|
case IOCTL_WFS_ATTACH_DETACH:
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_ATTACH_DETACH(%d)", command);
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_ATTACH_DETACH(%u)", request.request);
|
||||||
Memory::Write_U32(1, buffer_out);
|
Memory::Write_U32(1, request.buffer_out);
|
||||||
Memory::Write_U32(0, buffer_out + 4);
|
Memory::Write_U32(0, request.buffer_out + 4);
|
||||||
Memory::Write_U32(0, buffer_out + 8);
|
Memory::Write_U32(0, request.buffer_out + 8);
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
|
|
||||||
// TODO(wfs): Globbing is not really implemented, we just fake the one case
|
// TODO(wfs): Globbing is not really implemented, we just fake the one case
|
||||||
// (listing /vol/*) which is required to get the installer to work.
|
// (listing /vol/*) which is required to get the installer to work.
|
||||||
case IOCTL_WFS_GLOB_START:
|
case IOCTL_WFS_GLOB_START:
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GLOB_START(%d)", command);
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GLOB_START(%u)", request.request);
|
||||||
Memory::Memset(buffer_out, 0, buffer_out_size);
|
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
|
||||||
memcpy(Memory::GetPointer(buffer_out + 0x14), m_device_name.data(), m_device_name.size());
|
Memory::CopyToEmu(request.buffer_out + 0x14, m_device_name.data(), m_device_name.size());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFS_GLOB_NEXT:
|
case IOCTL_WFS_GLOB_NEXT:
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GLOB_NEXT(%d)", command);
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GLOB_NEXT(%u)", request.request);
|
||||||
return_error_code = WFS_EEMPTY;
|
return_error_code = WFS_EEMPTY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFS_GLOB_END:
|
case IOCTL_WFS_GLOB_END:
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GLOB_END(%d)", command);
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_GLOB_END(%u)", request.request);
|
||||||
Memory::Memset(buffer_out, 0, buffer_out_size);
|
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFS_OPEN:
|
case IOCTL_WFS_OPEN:
|
||||||
{
|
{
|
||||||
u32 mode = Memory::Read_U32(buffer_in);
|
u32 mode = Memory::Read_U32(request.buffer_in);
|
||||||
u16 path_len = Memory::Read_U16(buffer_in + 0x20);
|
u16 path_len = Memory::Read_U16(request.buffer_in + 0x20);
|
||||||
std::string path = Memory::GetString(buffer_in + 0x22, path_len);
|
std::string path = Memory::GetString(request.buffer_in + 0x22, path_len);
|
||||||
|
|
||||||
u16 fd = GetNewFileDescriptor();
|
u16 fd = GetNewFileDescriptor();
|
||||||
FileDescriptor* fd_obj = &m_fds[fd];
|
FileDescriptor* fd_obj = &m_fds[fd];
|
||||||
|
@ -115,13 +109,13 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::IOCtl(u32 command_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_OPEN(%s, %d) -> %d", path.c_str(), mode, fd);
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_OPEN(%s, %d) -> %d", path.c_str(), mode, fd);
|
||||||
Memory::Write_U16(fd, buffer_out + 0x14);
|
Memory::Write_U16(fd, request.buffer_out + 0x14);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IOCTL_WFS_CLOSE:
|
case IOCTL_WFS_CLOSE:
|
||||||
{
|
{
|
||||||
u16 fd = Memory::Read_U16(buffer_in + 0x4);
|
u16 fd = Memory::Read_U16(request.buffer_in + 0x4);
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_CLOSE(%d)", fd);
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFS_CLOSE(%d)", fd);
|
||||||
ReleaseFileDescriptor(fd);
|
ReleaseFileDescriptor(fd);
|
||||||
break;
|
break;
|
||||||
|
@ -129,9 +123,9 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::IOCtl(u32 command_address)
|
||||||
|
|
||||||
case IOCTL_WFS_READ:
|
case IOCTL_WFS_READ:
|
||||||
{
|
{
|
||||||
u32 addr = Memory::Read_U32(buffer_in);
|
u32 addr = Memory::Read_U32(request.buffer_in);
|
||||||
u16 fd = Memory::Read_U16(buffer_in + 0xC);
|
u16 fd = Memory::Read_U16(request.buffer_in + 0xC);
|
||||||
u32 size = Memory::Read_U32(buffer_in + 8);
|
u32 size = Memory::Read_U32(request.buffer_in + 8);
|
||||||
|
|
||||||
FileDescriptor* fd_obj = FindFileDescriptor(fd);
|
FileDescriptor* fd_obj = FindFileDescriptor(fd);
|
||||||
if (fd_obj == nullptr)
|
if (fd_obj == nullptr)
|
||||||
|
@ -158,24 +152,12 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::IOCtl(u32 command_address)
|
||||||
default:
|
default:
|
||||||
// TODO(wfs): Should be returning -3. However until we have everything
|
// TODO(wfs): Should be returning -3. However until we have everything
|
||||||
// properly stubbed it's easier to simulate the methods succeeding.
|
// properly stubbed it's easier to simulate the methods succeeding.
|
||||||
WARN_LOG(WII_IPC_HLE, "%s unimplemented IOCtl(0x%08x, size_in=%08x, size_out=%08x)\n%s\n%s",
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_HLE, LogTypes::LWARNING);
|
||||||
m_name.c_str(), command, buffer_in_size, buffer_out_size,
|
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
|
||||||
HexDump(Memory::GetPointer(buffer_in), buffer_in_size).c_str(),
|
|
||||||
HexDump(Memory::GetPointer(buffer_out), buffer_out_size).c_str());
|
|
||||||
Memory::Memset(buffer_out, 0, buffer_out_size);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(return_error_code, command_address + 4);
|
return GetDefaultReply(return_error_code);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_usb_wfssrv::IOCtlV(u32 command_address)
|
|
||||||
{
|
|
||||||
SIOCtlVBuffer command_buffer(command_address);
|
|
||||||
ERROR_LOG(WII_IPC_HLE, "IOCtlV on /dev/usb/wfssrv -- unsupported");
|
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address + 4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CWII_IPC_HLE_Device_usb_wfssrv::FileDescriptor*
|
CWII_IPC_HLE_Device_usb_wfssrv::FileDescriptor*
|
||||||
|
|
|
@ -23,8 +23,7 @@ class CWII_IPC_HLE_Device_usb_wfssrv : public IWII_IPC_HLE_Device
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_usb_wfssrv(u32 device_id, const std::string& device_name);
|
CWII_IPC_HLE_Device_usb_wfssrv(u32 device_id, const std::string& device_name);
|
||||||
|
|
||||||
IPCCommandResult IOCtl(u32 command_address) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 command_address) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// WFS device name, e.g. msc01/msc02.
|
// WFS device name, e.g. msc01/msc02.
|
||||||
|
|
|
@ -79,28 +79,16 @@ CWII_IPC_HLE_Device_wfsi::CWII_IPC_HLE_Device_wfsi(u32 device_id, const std::str
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_wfsi::Open(u32 command_address, u32 mode)
|
IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_HLE, "/dev/wfsi: Open");
|
|
||||||
return IWII_IPC_HLE_Device::Open(command_address, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtl(u32 command_address)
|
|
||||||
{
|
|
||||||
u32 command = Memory::Read_U32(command_address + 0xC);
|
|
||||||
u32 buffer_in = Memory::Read_U32(command_address + 0x10);
|
|
||||||
u32 buffer_in_size = Memory::Read_U32(command_address + 0x14);
|
|
||||||
u32 buffer_out = Memory::Read_U32(command_address + 0x18);
|
|
||||||
u32 buffer_out_size = Memory::Read_U32(command_address + 0x1C);
|
|
||||||
|
|
||||||
u32 return_error_code = IPC_SUCCESS;
|
u32 return_error_code = IPC_SUCCESS;
|
||||||
|
|
||||||
switch (command)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
case IOCTL_WFSI_PREPARE_DEVICE:
|
case IOCTL_WFSI_PREPARE_DEVICE:
|
||||||
{
|
{
|
||||||
u32 tmd_addr = Memory::Read_U32(buffer_in);
|
u32 tmd_addr = Memory::Read_U32(request.buffer_in);
|
||||||
u32 tmd_size = Memory::Read_U32(buffer_in + 4);
|
u32 tmd_size = Memory::Read_U32(request.buffer_in + 4);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFSI_PREPARE_DEVICE");
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFSI_PREPARE_DEVICE");
|
||||||
|
|
||||||
|
@ -135,11 +123,12 @@ IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtl(u32 command_address)
|
||||||
|
|
||||||
case IOCTL_WFSI_PREPARE_CONTENT:
|
case IOCTL_WFSI_PREPARE_CONTENT:
|
||||||
{
|
{
|
||||||
const char* ioctl_name = command == IOCTL_WFSI_PREPARE_PROFILE ? "IOCTL_WFSI_PREPARE_PROFILE" :
|
const char* ioctl_name = request.request == IOCTL_WFSI_PREPARE_PROFILE ?
|
||||||
"IOCTL_WFSI_PREPARE_CONTENT";
|
"IOCTL_WFSI_PREPARE_PROFILE" :
|
||||||
|
"IOCTL_WFSI_PREPARE_CONTENT";
|
||||||
|
|
||||||
// Initializes the IV from the index of the content in the TMD contents.
|
// Initializes the IV from the index of the content in the TMD contents.
|
||||||
u32 content_id = Memory::Read_U32(buffer_in + 8);
|
u32 content_id = Memory::Read_U32(request.buffer_in + 8);
|
||||||
TMDReader::Content content_info;
|
TMDReader::Content content_info;
|
||||||
if (!m_tmd.FindContentById(content_id, &content_info))
|
if (!m_tmd.FindContentById(content_id, &content_info))
|
||||||
{
|
{
|
||||||
|
@ -161,12 +150,13 @@ IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtl(u32 command_address)
|
||||||
case IOCTL_WFSI_IMPORT_PROFILE:
|
case IOCTL_WFSI_IMPORT_PROFILE:
|
||||||
case IOCTL_WFSI_IMPORT_CONTENT:
|
case IOCTL_WFSI_IMPORT_CONTENT:
|
||||||
{
|
{
|
||||||
const char* ioctl_name = command == IOCTL_WFSI_IMPORT_PROFILE ? "IOCTL_WFSI_IMPORT_PROFILE" :
|
const char* ioctl_name = request.request == IOCTL_WFSI_IMPORT_PROFILE ?
|
||||||
"IOCTL_WFSI_IMPORT_CONTENT";
|
"IOCTL_WFSI_IMPORT_PROFILE" :
|
||||||
|
"IOCTL_WFSI_IMPORT_CONTENT";
|
||||||
|
|
||||||
u32 content_id = Memory::Read_U32(buffer_in + 0xC);
|
u32 content_id = Memory::Read_U32(request.buffer_in + 0xC);
|
||||||
u32 input_ptr = Memory::Read_U32(buffer_in + 0x10);
|
u32 input_ptr = Memory::Read_U32(request.buffer_in + 0x10);
|
||||||
u32 input_size = Memory::Read_U32(buffer_in + 0x14);
|
u32 input_size = Memory::Read_U32(request.buffer_in + 0x14);
|
||||||
INFO_LOG(WII_IPC_HLE, "%s: %08x bytes of data at %08x from content id %d", ioctl_name,
|
INFO_LOG(WII_IPC_HLE, "%s: %08x bytes of data at %08x from content id %d", ioctl_name,
|
||||||
content_id, input_ptr, input_size);
|
content_id, input_ptr, input_size);
|
||||||
|
|
||||||
|
@ -181,7 +171,7 @@ IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtl(u32 command_address)
|
||||||
case IOCTL_WFSI_FINALIZE_PROFILE:
|
case IOCTL_WFSI_FINALIZE_PROFILE:
|
||||||
case IOCTL_WFSI_FINALIZE_CONTENT:
|
case IOCTL_WFSI_FINALIZE_CONTENT:
|
||||||
{
|
{
|
||||||
const char* ioctl_name = command == IOCTL_WFSI_FINALIZE_PROFILE ?
|
const char* ioctl_name = request.request == IOCTL_WFSI_FINALIZE_PROFILE ?
|
||||||
"IOCTL_WFSI_FINALIZE_PROFILE" :
|
"IOCTL_WFSI_FINALIZE_PROFILE" :
|
||||||
"IOCTL_WFSI_FINALIZE_CONTENT";
|
"IOCTL_WFSI_FINALIZE_CONTENT";
|
||||||
INFO_LOG(WII_IPC_HLE, "%s", ioctl_name);
|
INFO_LOG(WII_IPC_HLE, "%s", ioctl_name);
|
||||||
|
@ -225,7 +215,7 @@ IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtl(u32 command_address)
|
||||||
|
|
||||||
case IOCTL_WFSI_SET_DEVICE_NAME:
|
case IOCTL_WFSI_SET_DEVICE_NAME:
|
||||||
INFO_LOG(WII_IPC_HLE, "IOCTL_WFSI_SET_DEVICE_NAME");
|
INFO_LOG(WII_IPC_HLE, "IOCTL_WFSI_SET_DEVICE_NAME");
|
||||||
m_device_name = Memory::GetString(buffer_in);
|
m_device_name = Memory::GetString(request.buffer_in);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_WFSI_APPLY_TITLE_PROFILE:
|
case IOCTL_WFSI_APPLY_TITLE_PROFILE:
|
||||||
|
@ -243,21 +233,10 @@ IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtl(u32 command_address)
|
||||||
// TODO(wfs): Should be returning an error. However until we have
|
// TODO(wfs): Should be returning an error. However until we have
|
||||||
// everything properly stubbed it's easier to simulate the methods
|
// everything properly stubbed it's easier to simulate the methods
|
||||||
// succeeding.
|
// succeeding.
|
||||||
WARN_LOG(WII_IPC_HLE, "%s unimplemented IOCtl(0x%08x, size_in=%08x, size_out=%08x)\n%s\n%s",
|
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_HLE, LogTypes::LWARNING);
|
||||||
m_name.c_str(), command, buffer_in_size, buffer_out_size,
|
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
|
||||||
HexDump(Memory::GetPointer(buffer_in), buffer_in_size).c_str(),
|
|
||||||
HexDump(Memory::GetPointer(buffer_out), buffer_out_size).c_str());
|
|
||||||
Memory::Memset(buffer_out, 0, buffer_out_size);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(return_error_code, command_address + 4);
|
return GetDefaultReply(return_error_code);
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_wfsi::IOCtlV(u32 command_address)
|
|
||||||
{
|
|
||||||
ERROR_LOG(WII_IPC_HLE, "IOCtlV on /dev/wfsi -- unsupported");
|
|
||||||
Memory::Write_U32(IPC_EINVAL, command_address + 4);
|
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,7 @@ class CWII_IPC_HLE_Device_wfsi : public IWII_IPC_HLE_Device
|
||||||
public:
|
public:
|
||||||
CWII_IPC_HLE_Device_wfsi(u32 device_id, const std::string& device_name);
|
CWII_IPC_HLE_Device_wfsi(u32 device_id, const std::string& device_name);
|
||||||
|
|
||||||
IPCCommandResult Open(u32 command_address, u32 mode) override;
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtl(u32 command_address) override;
|
|
||||||
IPCCommandResult IOCtlV(u32 command_address) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_device_name;
|
std::string m_device_name;
|
||||||
|
|
|
@ -187,28 +187,23 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
{
|
{
|
||||||
s32 ReturnValue = 0;
|
s32 ReturnValue = 0;
|
||||||
bool forceNonBlock = false;
|
bool forceNonBlock = false;
|
||||||
IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(it->_CommandAddress));
|
IPCCommandType ct = it->request.command;
|
||||||
if (!it->is_ssl && ct == IPC_CMD_IOCTL)
|
if (!it->is_ssl && ct == IPC_CMD_IOCTL)
|
||||||
{
|
{
|
||||||
u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10);
|
IOSIOCtlRequest ioctl{it->request.address};
|
||||||
u32 BufferInSize = Memory::Read_U32(it->_CommandAddress + 0x14);
|
|
||||||
u32 BufferOut = Memory::Read_U32(it->_CommandAddress + 0x18);
|
|
||||||
u32 BufferOutSize = Memory::Read_U32(it->_CommandAddress + 0x1C);
|
|
||||||
|
|
||||||
switch (it->net_type)
|
switch (it->net_type)
|
||||||
{
|
{
|
||||||
case IOCTL_SO_FCNTL:
|
case IOCTL_SO_FCNTL:
|
||||||
{
|
{
|
||||||
u32 cmd = Memory::Read_U32(BufferIn + 4);
|
u32 cmd = Memory::Read_U32(ioctl.buffer_in + 4);
|
||||||
u32 arg = Memory::Read_U32(BufferIn + 8);
|
u32 arg = Memory::Read_U32(ioctl.buffer_in + 8);
|
||||||
ReturnValue = FCntl(cmd, arg);
|
ReturnValue = FCntl(cmd, arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_SO_BIND:
|
case IOCTL_SO_BIND:
|
||||||
{
|
{
|
||||||
// u32 has_addr = Memory::Read_U32(BufferIn + 0x04);
|
|
||||||
sockaddr_in local_name;
|
sockaddr_in local_name;
|
||||||
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08);
|
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(ioctl.buffer_in + 8);
|
||||||
WiiSockMan::Convert(*wii_name, local_name);
|
WiiSockMan::Convert(*wii_name, local_name);
|
||||||
|
|
||||||
int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name));
|
int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name));
|
||||||
|
@ -220,9 +215,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
}
|
}
|
||||||
case IOCTL_SO_CONNECT:
|
case IOCTL_SO_CONNECT:
|
||||||
{
|
{
|
||||||
// u32 has_addr = Memory::Read_U32(BufferIn + 0x04);
|
|
||||||
sockaddr_in local_name;
|
sockaddr_in local_name;
|
||||||
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08);
|
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(ioctl.buffer_in + 8);
|
||||||
WiiSockMan::Convert(*wii_name, local_name);
|
WiiSockMan::Convert(*wii_name, local_name);
|
||||||
|
|
||||||
int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name));
|
int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name));
|
||||||
|
@ -234,10 +228,10 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
}
|
}
|
||||||
case IOCTL_SO_ACCEPT:
|
case IOCTL_SO_ACCEPT:
|
||||||
{
|
{
|
||||||
if (BufferOutSize > 0)
|
if (ioctl.buffer_out_size > 0)
|
||||||
{
|
{
|
||||||
sockaddr_in local_name;
|
sockaddr_in local_name;
|
||||||
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut);
|
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(ioctl.buffer_out);
|
||||||
WiiSockMan::Convert(*wii_name, local_name);
|
WiiSockMan::Convert(*wii_name, local_name);
|
||||||
|
|
||||||
socklen_t addrlen = sizeof(sockaddr_in);
|
socklen_t addrlen = sizeof(sockaddr_in);
|
||||||
|
@ -254,10 +248,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
|
|
||||||
WiiSockMan::GetInstance().AddSocket(ReturnValue);
|
WiiSockMan::GetInstance().AddSocket(ReturnValue);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT "
|
ioctl.Log("IOCTL_SO_ACCEPT", LogTypes::WII_IPC_NET);
|
||||||
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
|
||||||
BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -275,34 +266,34 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
}
|
}
|
||||||
else if (ct == IPC_CMD_IOCTLV)
|
else if (ct == IPC_CMD_IOCTLV)
|
||||||
{
|
{
|
||||||
SIOCtlVBuffer CommandBuffer(it->_CommandAddress);
|
IOSIOCtlVRequest ioctlv{it->request.address};
|
||||||
u32 BufferIn = 0, BufferIn2 = 0;
|
u32 BufferIn = 0, BufferIn2 = 0;
|
||||||
u32 BufferInSize = 0, BufferInSize2 = 0;
|
u32 BufferInSize = 0, BufferInSize2 = 0;
|
||||||
u32 BufferOut = 0, BufferOut2 = 0;
|
u32 BufferOut = 0, BufferOut2 = 0;
|
||||||
u32 BufferOutSize = 0, BufferOutSize2 = 0;
|
u32 BufferOutSize = 0, BufferOutSize2 = 0;
|
||||||
|
|
||||||
if (CommandBuffer.InBuffer.size() > 0)
|
if (ioctlv.in_vectors.size() > 0)
|
||||||
{
|
{
|
||||||
BufferIn = CommandBuffer.InBuffer.at(0).m_Address;
|
BufferIn = ioctlv.in_vectors.at(0).address;
|
||||||
BufferInSize = CommandBuffer.InBuffer.at(0).m_Size;
|
BufferInSize = ioctlv.in_vectors.at(0).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 0)
|
if (ioctlv.io_vectors.size() > 0)
|
||||||
{
|
{
|
||||||
BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
|
BufferOut = ioctlv.io_vectors.at(0).address;
|
||||||
BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
|
BufferOutSize = ioctlv.io_vectors.at(0).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 1)
|
if (ioctlv.io_vectors.size() > 1)
|
||||||
{
|
{
|
||||||
BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
|
BufferOut2 = ioctlv.io_vectors.at(1).address;
|
||||||
BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
|
BufferOutSize2 = ioctlv.io_vectors.at(1).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CommandBuffer.InBuffer.size() > 1)
|
if (ioctlv.in_vectors.size() > 1)
|
||||||
{
|
{
|
||||||
BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address;
|
BufferIn2 = ioctlv.in_vectors.at(1).address;
|
||||||
BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size;
|
BufferInSize2 = ioctlv.in_vectors.at(1).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->is_ssl)
|
if (it->is_ssl)
|
||||||
|
@ -576,8 +567,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
"IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d", fd,
|
"IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d", fd,
|
||||||
it->is_ssl ? (int)it->ssl_type : (int)it->net_type, ReturnValue, nonBlock,
|
it->is_ssl ? (int)it->ssl_type : (int)it->net_type, ReturnValue, nonBlock,
|
||||||
forceNonBlock);
|
forceNonBlock);
|
||||||
Memory::Write_U32(ReturnValue, it->_CommandAddress + 4);
|
WII_IPC_HLE_Interface::EnqueueReply(it->request, ReturnValue);
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(it->_CommandAddress);
|
|
||||||
it = pending_sockops.erase(it);
|
it = pending_sockops.erase(it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -587,16 +577,16 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiiSocket::DoSock(u32 _CommandAddress, NET_IOCTL type)
|
void WiiSocket::DoSock(IOSRequest request, NET_IOCTL type)
|
||||||
{
|
{
|
||||||
sockop so = {_CommandAddress, false};
|
sockop so = {request, false};
|
||||||
so.net_type = type;
|
so.net_type = type;
|
||||||
pending_sockops.push_back(so);
|
pending_sockops.push_back(so);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiiSocket::DoSock(u32 _CommandAddress, SSL_IOCTL type)
|
void WiiSocket::DoSock(IOSRequest request, SSL_IOCTL type)
|
||||||
{
|
{
|
||||||
sockop so = {_CommandAddress, true};
|
sockop so = {request, true};
|
||||||
so.ssl_type = type;
|
so.ssl_type = type;
|
||||||
pending_sockops.push_back(so);
|
pending_sockops.push_back(so);
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ class WiiSocket
|
||||||
{
|
{
|
||||||
struct sockop
|
struct sockop
|
||||||
{
|
{
|
||||||
u32 _CommandAddress;
|
IOSRequest request;
|
||||||
bool is_ssl;
|
bool is_ssl;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -191,8 +191,8 @@ private:
|
||||||
s32 CloseFd();
|
s32 CloseFd();
|
||||||
s32 FCntl(u32 cmd, u32 arg);
|
s32 FCntl(u32 cmd, u32 arg);
|
||||||
|
|
||||||
void DoSock(u32 _CommandAddress, NET_IOCTL type);
|
void DoSock(IOSRequest request, NET_IOCTL type);
|
||||||
void DoSock(u32 _CommandAddress, SSL_IOCTL type);
|
void DoSock(IOSRequest request, SSL_IOCTL type);
|
||||||
void Update(bool read, bool write, bool except);
|
void Update(bool read, bool write, bool except);
|
||||||
bool IsValid() const { return fd >= 0; }
|
bool IsValid() const { return fd >= 0; }
|
||||||
public:
|
public:
|
||||||
|
@ -223,19 +223,18 @@ public:
|
||||||
void SetLastNetError(s32 error) { errno_last = error; }
|
void SetLastNetError(s32 error) { errno_last = error; }
|
||||||
void Clean() { WiiSockets.clear(); }
|
void Clean() { WiiSockets.clear(); }
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DoSock(s32 sock, u32 CommandAddress, T type)
|
void DoSock(s32 sock, const IOSRequest& request, T type)
|
||||||
{
|
{
|
||||||
auto socket_entry = WiiSockets.find(sock);
|
auto socket_entry = WiiSockets.find(sock);
|
||||||
if (socket_entry == WiiSockets.end())
|
if (socket_entry == WiiSockets.end())
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_NET, "DoSock: Error, fd not found (%08x, %08X, %08X)", sock, CommandAddress,
|
ERROR_LOG(WII_IPC_NET, "DoSock: Error, fd not found (%08x, %08X, %08X)", sock,
|
||||||
type);
|
request.address, type);
|
||||||
Memory::Write_U32(-SO_EBADF, CommandAddress + 4);
|
WII_IPC_HLE_Interface::EnqueueReply(request, -SO_EBADF);
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(CommandAddress);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
socket_entry->second.DoSock(CommandAddress, type);
|
socket_entry->second.DoSock(request, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
||||||
static std::thread g_save_thread;
|
static std::thread g_save_thread;
|
||||||
|
|
||||||
// Don't forget to increase this after doing changes on the savestate system
|
// Don't forget to increase this after doing changes on the savestate system
|
||||||
static const u32 STATE_VERSION = 68; // Last changed in PR 4638
|
static const u32 STATE_VERSION = 69; // Last changed in PR 4661
|
||||||
|
|
||||||
// Maps savestate versions to Dolphin versions.
|
// Maps savestate versions to Dolphin versions.
|
||||||
// Versions after 42 don't need to be added to this list,
|
// Versions after 42 don't need to be added to this list,
|
||||||
|
|
Loading…
Reference in New Issue