IOS: Convert the IOS kernel HLE code to a class

This changes the main IOS code (roughly the equivalent of the kernel)
to a class instead of being a set of free functions + tons of static
variables.

The reason for this change is that keeping tons of static variables
like that prevents us from making an IOS instance and reusing IOS
code easily.

Converting the IOS code to a class also allows us to mostly decouple
IOS from the PPC emulation.

The more interesting changes are in Core/IOS/IOS. Everything else is
mostly just boring stuff required by this change...

* Because the devices themselves call back to the main IOS code
  for various things (getting the current version, replying to a
  request, and other syscall-like functions), just like processes in
  IOS call kernel syscalls, we have to pass a reference to the kernel
  to anything that uses IOS syscalls.

* Change DoState to save device names instead of device IDs to simplify
  AddDevice() and get rid of an ugly static count.

* Change ES_Launch's ack to be sent at IOS boot, now that we can do
  this properly.
This commit is contained in:
Léo Lam 2017-04-29 16:11:22 +02:00
parent fcc2ed4550
commit 2fc5047d26
88 changed files with 1477 additions and 1428 deletions

View File

@ -27,7 +27,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/VideoInterface.h"
#include "Core/Host.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PPCSymbolDB.h"

View File

@ -23,7 +23,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PowerPC.h"
@ -289,7 +289,7 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id)
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
if (!IOS::HLE::Reload(ios_title_id))
if (!IOS::HLE::GetIOS()->BootIOS(ios_title_id))
{
return false;
}

View File

@ -16,7 +16,7 @@
#include "Core/Boot/Boot.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "DiscIO/NANDContentLoader.h"
@ -88,7 +88,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
return false;
IOS::HLE::Device::ES::LoadWAD(_pFilename);
if (!IOS::HLE::BootstrapPPC(ContentLoader))
if (!IOS::HLE::GetIOS()->BootstrapPPC(ContentLoader))
return false;
return true;

View File

@ -147,7 +147,8 @@ set(SRCS
HW/WiiSaveCrypted.cpp
IOS/Device.cpp
IOS/DeviceStub.cpp
IOS/IPC.cpp
IOS/IOS.cpp
IOS/MemoryValues.cpp
IOS/MIOS.cpp
IOS/DI/DI.cpp
IOS/ES/ES.cpp

View File

@ -50,7 +50,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/Wiimote.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/NetPlayClient.h"
#include "Core/NetPlayProto.h"
@ -952,7 +952,9 @@ void UpdateWantDeterminism(bool initial)
bool was_unpaused = Core::PauseAndLock(true);
s_wants_determinism = new_want_determinism;
IOS::HLE::UpdateWantDeterminism(new_want_determinism);
const auto ios = IOS::HLE::GetIOS();
if (ios)
ios->UpdateWantDeterminism(new_want_determinism);
Fifo::UpdateWantDeterminism(new_want_determinism);
// We need to clear the cache because some parts of the JIT depend on want_determinism, e.g. use
// of FMA.

View File

@ -174,7 +174,8 @@
<ClCompile Include="HW\WiiSaveCrypted.cpp" />
<ClCompile Include="IOS\Device.cpp" />
<ClCompile Include="IOS\DeviceStub.cpp" />
<ClCompile Include="IOS\IPC.cpp" />
<ClCompile Include="IOS\IOS.cpp" />
<ClCompile Include="IOS\MemoryValues.cpp" />
<ClCompile Include="IOS\MIOS.cpp" />
<ClCompile Include="IOS\DI\DI.cpp" />
<ClCompile Include="IOS\ES\ES.cpp" />
@ -431,7 +432,8 @@
<ClInclude Include="HW\WII_IPC.h" />
<ClInclude Include="IOS\Device.h" />
<ClInclude Include="IOS\DeviceStub.h" />
<ClInclude Include="IOS\IPC.h" />
<ClInclude Include="IOS\IOS.h" />
<ClInclude Include="IOS\MemoryValues.h" />
<ClInclude Include="IOS\MIOS.h" />
<ClInclude Include="IOS\DI\DI.h" />
<ClInclude Include="IOS\ES\ES.h" />

View File

@ -790,7 +790,10 @@
<ClCompile Include="IOS\Network\ICMPLin.cpp">
<Filter>IOS\Network</Filter>
</ClCompile>
<ClCompile Include="IOS\IPC.cpp">
<ClCompile Include="IOS\IOS.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\MemoryValues.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\MIOS.cpp">
@ -1504,7 +1507,10 @@
<ClInclude Include="IOS\Device.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\IPC.h">
<ClInclude Include="IOS\IOS.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\MemoryValues.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\MIOS.h">

View File

@ -28,7 +28,7 @@
#include "Core/HW/StreamADPCM.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/DI/DI.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "DiscIO/Enums.h"
@ -1136,7 +1136,7 @@ void FinishExecutingCommand(ReplyType reply_type, DIInterruptType interrupt_type
case ReplyType::IOS:
{
auto di = IOS::HLE::GetDeviceByName("/dev/di");
auto di = IOS::HLE::GetIOS()->GetDeviceByName("/dev/di");
if (di)
std::static_pointer_cast<IOS::HLE::Device::DI>(di)->FinishIOCtl(interrupt_type);
break;

View File

@ -21,7 +21,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/WII_IPC.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/State.h"
#include "Core/WiiRoot.h"
@ -102,7 +102,7 @@ void DoState(PointerWrap& p)
{
IOS::DoState(p);
p.DoMarker("IOS");
IOS::HLE::DoState(p);
IOS::HLE::GetIOS()->DoState(p);
p.DoMarker("IOS::HLE");
}

View File

@ -11,7 +11,7 @@
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/PowerPC/PowerPC.h"
@ -210,22 +210,24 @@ static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate)
static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->ResetButton();
}
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->ResetButton();
}
static void IOSNotifyPowerButtonCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->PowerButton();
}
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->PowerButton();
}
void ResetButton_Tap()

View File

@ -57,7 +57,7 @@ IPC_HLE_PERIOD: For the Wii Remote this is the call schedule:
#include "Core/HW/DSP.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/VideoInterface.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PowerPC.h"
#include "VideoCommon/Fifo.h"
@ -112,7 +112,7 @@ static void IPC_HLE_UpdateCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
IOS::HLE::UpdateDevices();
IOS::HLE::GetIOS()->UpdateDevices();
CoreTiming::ScheduleEvent(s_ipc_hle_period - cyclesLate, et_IPC_HLE);
}
}

View File

@ -9,7 +9,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
// This is the intercommunication between ARM and PPC. Currently only PPC actually uses it, because
// of the IOS HLE
@ -153,8 +153,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::ComplexWrite<u32>([](u32, u32 val) {
ctrl.ppc(val);
if (ctrl.X1)
HLE::EnqueueRequest(ppc_msg);
HLE::Update();
HLE::GetIOS()->EnqueueIPCRequest(ppc_msg);
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));
@ -163,7 +163,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](u32, u32 val) {
ppc_irq_flags &= ~val;
HLE::Update();
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));
@ -172,7 +172,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
ppc_irq_masks = val;
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
Reset();
HLE::Update();
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));

View File

@ -24,7 +24,7 @@ namespace HLE
{
namespace Device
{
DI::DI(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
DI::DI(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}
@ -76,7 +76,7 @@ void DI::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type)
// This command has been executed, so it's removed from the queue
u32 command_address = m_commands_to_execute.front();
m_commands_to_execute.pop_front();
EnqueueReply(IOCtlRequest{command_address}, interrupt_type);
m_ios.EnqueueIPCReply(IOCtlRequest{command_address}, interrupt_type);
// DVDInterface is now ready to execute another command,
// so we start executing a command from the queue if there is one

View File

@ -9,7 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -27,7 +27,7 @@ namespace Device
class DI : public Device
{
public:
DI(u32 device_id, const std::string& device_name);
DI(Kernel& ios, const std::string& device_name);
void DoState(PointerWrap& p) override;

View File

@ -10,7 +10,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -26,8 +26,12 @@ OpenRequest::OpenRequest(const u32 address_) : Request(address_)
{
path = Memory::GetString(Memory::Read_U32(address + 0xc));
flags = static_cast<OpenMode>(Memory::Read_U32(address + 0x10));
uid = GetUIDForPPC();
gid = GetGIDForPPC();
const Kernel* ios = GetIOS();
if (ios)
{
uid = ios->GetUidForPPC();
gid = ios->GetGidForPPC();
}
}
ReadWriteRequest::ReadWriteRequest(const u32 address_) : Request(address_)
@ -129,8 +133,8 @@ void IOCtlVRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TY
namespace Device
{
Device::Device(const u32 device_id, const std::string& device_name, const DeviceType type)
: m_name(device_name), m_device_id(device_id), m_device_type(type)
Device::Device(Kernel& ios, const std::string& device_name, const DeviceType type)
: m_ios(ios), m_name(device_name), m_device_type(type)
{
}
@ -143,7 +147,6 @@ void Device::DoState(PointerWrap& p)
void Device::DoStateShared(PointerWrap& p)
{
p.Do(m_name);
p.Do(m_device_id);
p.Do(m_device_type);
p.Do(m_is_active);
}

View File

@ -11,7 +11,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -172,7 +172,7 @@ public:
OH0, // OH0 child devices which are created dynamically.
};
Device(u32 device_id, const std::string& device_name, DeviceType type = DeviceType::Static);
Device(Kernel& ios, const std::string& device_name, DeviceType type = DeviceType::Static);
virtual ~Device() = default;
// Release any resources which might interfere with savestating.
@ -181,7 +181,6 @@ public:
void DoStateShared(PointerWrap& p);
const std::string& GetDeviceName() const { return m_name; }
u32 GetDeviceID() const { return m_device_id; }
// Replies to Open and Close requests are sent by the IPC request handler (HandleCommand),
// not by the devices themselves.
virtual ReturnCode Open(const OpenRequest& request);
@ -199,9 +198,10 @@ public:
static IPCCommandResult GetNoReply();
protected:
Kernel& m_ios;
std::string m_name;
// STATE_TO_SAVE
u32 m_device_id;
DeviceType m_device_type;
bool m_is_active = false;

View File

@ -11,10 +11,6 @@ namespace HLE
{
namespace Device
{
Stub::Stub(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
{
}
ReturnCode Stub::Open(const OpenRequest& request)
{
WARN_LOG(IOS, "%s faking Open()", m_name.c_str());

View File

@ -8,7 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -19,8 +19,8 @@ namespace Device
class Stub final : public Device
{
public:
Stub(u32 device_id, const std::string& device_name);
// Inherit the constructor from the Device class, since we don't need to do anything special.
using Device::Device;
ReturnCode Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;

View File

@ -55,7 +55,7 @@ static void FinishAllStaleImports()
File::CreateDir(import_dir);
}
ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
ES::ES(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
FinishAllStaleImports();
@ -155,7 +155,7 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request)
return GetDefaultReply(IPC_SUCCESS);
}
static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
static bool UpdateUIDAndGID(Kernel& kernel, const IOS::ES::TMDReader& tmd)
{
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
const u64 title_id = tmd.GetTitleId();
@ -165,8 +165,8 @@ static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
ERROR_LOG(IOS_ES, "Failed to get UID for title %016" PRIx64, title_id);
return false;
}
SetUIDForPPC(uid);
SetGIDForPPC(tmd.GetGroupId());
kernel.SetUidForPPC(uid);
kernel.SetGidForPPC(tmd.GetGroupId());
return true;
}
@ -197,7 +197,7 @@ IPCCommandResult ES::SetUID(u32 uid, const IOCtlVRequest& request)
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
if (!UpdateUIDAndGID(tmd))
if (!UpdateUIDAndGID(m_ios, tmd))
{
ERROR_LOG(IOS_ES, "SetUID: Failed to get UID for title %016" PRIx64, title_id);
return GetDefaultReply(ES_SHORT_READ);
@ -225,7 +225,7 @@ bool ES::LaunchTitle(u64 title_id, bool skip_reload)
bool ES::LaunchIOS(u64 ios_title_id)
{
return Reload(ios_title_id);
return m_ios.BootIOS(ios_title_id);
}
bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload)
@ -266,14 +266,14 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload)
// Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles
// are installed, we can only do this for PPC titles.
if (!UpdateUIDAndGID(s_title_context.tmd))
if (!UpdateUIDAndGID(m_ios, s_title_context.tmd))
{
s_title_context.Clear();
INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: (none)");
return false;
}
return BootstrapPPC(content_loader);
return m_ios.BootstrapPPC(content_loader);
}
void ES::Context::DoState(PointerWrap& p)
@ -555,11 +555,9 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
if (!LaunchTitle(TitleID))
return GetDefaultReply(FS_ENOENT);
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
// involves restarting IOS; IOS generates two acknowledgements in a row.
// Note: If the launch succeeded, we should not write anything to the command buffer as
// IOS does not even reply unless it failed.
EnqueueCommandAcknowledgement(request.address, 0);
// ES_LAUNCH involves restarting IOS, which results in two acknowledgements in a row
// (one from the previous IOS for this IPC request, and one from the new one as it boots).
// Nothing should be written to the command buffer if the launch succeeded for obvious reasons.
return GetNoReply();
}
@ -570,13 +568,12 @@ IPCCommandResult ES::LaunchBC(const IOCtlVRequest& request)
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
// An alternative way to do this is to check whether the current active IOS is MIOS.
if (GetVersion() == 0x101)
if (m_ios.GetVersion() == 0x101)
return GetDefaultReply(ES_EINVAL);
if (!LaunchTitle(0x0000000100000100))
return GetDefaultReply(FS_ENOENT);
EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply();
}
@ -633,7 +630,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
// clear the cache to avoid content access mismatches.
DiscIO::CNANDContentManager::Access().ClearCache();
if (!UpdateUIDAndGID(s_title_context.tmd))
if (!UpdateUIDAndGID(*GetIOS(), s_title_context.tmd))
{
return ES_SHORT_READ;
}

View File

@ -12,7 +12,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -43,11 +43,11 @@ struct TitleContext
class ES final : public Device
{
public:
ES(u32 device_id, const std::string& device_name);
ES(Kernel& ios, const std::string& device_name);
static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket);
static void LoadWAD(const std::string& _rContentFile);
static bool LaunchTitle(u64 title_id, bool skip_reload = false);
bool LaunchTitle(u64 title_id, bool skip_reload = false);
// Internal implementation of the ES_DECRYPT ioctlv.
static void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output);
@ -265,8 +265,8 @@ private:
ContextArray::iterator FindActiveContext(u32 fd);
ContextArray::iterator FindInactiveContext();
static bool LaunchIOS(u64 ios_title_id);
static bool LaunchPPCTitle(u64 title_id, bool skip_reload);
bool LaunchIOS(u64 ios_title_id);
bool LaunchPPCTitle(u64 title_id, bool skip_reload);
static TitleContext& GetTitleContext();
static const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id);

View File

@ -33,7 +33,7 @@ static bool IsValidWiiPath(const std::string& path)
namespace Device
{
FS::FS(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
FS::FS(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
const std::string tmp_dir = BuildFilename("/tmp");
File::DeleteDirRecursively(tmp_dir);

View File

@ -8,7 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -32,7 +32,7 @@ namespace Device
class FS : public Device
{
public:
FS(u32 device_id, const std::string& device_name);
FS(Kernel& ios, const std::string& device_name);
void DoState(PointerWrap& p) override;

View File

@ -15,7 +15,7 @@
#include "Common/NandPaths.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -71,14 +71,14 @@ void CreateVirtualFATFilesystem()
namespace Device
{
FileIO::FileIO(u32 device_id, const std::string& device_name)
: Device(device_id, device_name, DeviceType::FileIO)
FileIO::FileIO(Kernel& ios, const std::string& device_name)
: Device(ios, device_name, DeviceType::FileIO)
{
}
ReturnCode FileIO::Close(u32 fd)
{
INFO_LOG(IOS_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id);
INFO_LOG(IOS_FILEIO, "FileIO: Close %s", m_name.c_str());
m_Mode = 0;
// Let go of our pointer to the file, it will automatically close if we are the last handle

View File

@ -9,7 +9,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -30,7 +30,7 @@ namespace Device
class FileIO : public Device
{
public:
FileIO(u32 device_id, const std::string& device_name);
FileIO(Kernel& ios, const std::string& device_name);
ReturnCode Close(u32 fd) override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -0,0 +1,654 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/IOS/IOS.h"
#include <algorithm>
#include <array>
#include <cinttypes>
#include <deque>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
#include "Common/Assert.h"
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/Boot/Boot_DOL.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/WII_IPC.h"
#include "Core/IOS/DI/DI.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/DeviceStub.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/FS/FS.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/MIOS.h"
#include "Core/IOS/MemoryValues.h"
#include "Core/IOS/Network/IP/Top.h"
#include "Core/IOS/Network/KD/NetKDRequest.h"
#include "Core/IOS/Network/KD/NetKDTime.h"
#include "Core/IOS/Network/NCD/Manage.h"
#include "Core/IOS/Network/SSL.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/IOS/Network/WD/Command.h"
#include "Core/IOS/SDIO/SDIOSlot0.h"
#include "Core/IOS/STM/STM.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/BTReal.h"
#include "Core/IOS/USB/OH0/OH0.h"
#include "Core/IOS/USB/OH0/OH0Device.h"
#include "Core/IOS/USB/USB_HID/HIDv4.h"
#include "Core/IOS/USB/USB_KBD.h"
#include "Core/IOS/USB/USB_VEN/VEN.h"
#include "Core/IOS/WFS/WFSI.h"
#include "Core/IOS/WFS/WFSSRV.h"
#include "Core/PowerPC/PowerPC.h"
#include "DiscIO/NANDContentLoader.h"
namespace IOS
{
namespace HLE
{
static std::unique_ptr<Kernel> s_ios;
constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
static CoreTiming::EventType* s_event_enqueue;
static CoreTiming::EventType* s_event_sdio_notify;
enum class MemorySetupType
{
IOSReload,
Full,
};
constexpr u32 ADDR_MEM1_SIZE = 0x3100;
constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104;
constexpr u32 ADDR_MEM1_END = 0x3108;
constexpr u32 ADDR_MEM1_ARENA_BEGIN = 0x310c;
constexpr u32 ADDR_MEM1_ARENA_END = 0x3110;
constexpr u32 ADDR_PH1 = 0x3114;
constexpr u32 ADDR_MEM2_SIZE = 0x3118;
constexpr u32 ADDR_MEM2_SIM_SIZE = 0x311c;
constexpr u32 ADDR_MEM2_END = 0x3120;
constexpr u32 ADDR_MEM2_ARENA_BEGIN = 0x3124;
constexpr u32 ADDR_MEM2_ARENA_END = 0x3128;
constexpr u32 ADDR_PH2 = 0x312c;
constexpr u32 ADDR_IPC_BUFFER_BEGIN = 0x3130;
constexpr u32 ADDR_IPC_BUFFER_END = 0x3134;
constexpr u32 ADDR_HOLLYWOOD_REVISION = 0x3138;
constexpr u32 ADDR_PH3 = 0x313c;
constexpr u32 ADDR_IOS_VERSION = 0x3140;
constexpr u32 ADDR_IOS_DATE = 0x3144;
constexpr u32 ADDR_UNKNOWN_BEGIN = 0x3148;
constexpr u32 ADDR_UNKNOWN_END = 0x314c;
constexpr u32 ADDR_PH4 = 0x3150;
constexpr u32 ADDR_PH5 = 0x3154;
constexpr u32 ADDR_RAM_VENDOR = 0x3158;
constexpr u32 ADDR_BOOT_FLAG = 0x315c;
constexpr u32 ADDR_APPLOADER_FLAG = 0x315d;
constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e;
constexpr u32 ADDR_SYSMENU_SYNC = 0x3160;
// The title ID is a u64 where the first 32 bits are used for the title type.
// For IOS title IDs, the type will always be 00000001 (system), and the lower 32 bits
// are used for the IOS major version -- which is what we want here.
u32 Kernel::GetVersion() const
{
return static_cast<u32>(m_title_id);
}
constexpr u32 PLACEHOLDER = 0xDEADBEEF;
static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
{
auto target_imv = std::find_if(
GetMemoryValues().begin(), GetMemoryValues().end(),
[&](const MemoryValues& imv) { return imv.ios_number == (ios_title_id & 0xffff); });
if (target_imv == GetMemoryValues().end())
{
ERROR_LOG(IOS, "Unknown IOS version: %016" PRIx64, ios_title_id);
return false;
}
if (setup_type == MemorySetupType::IOSReload)
{
Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
// These values are written by the IOS kernel as part of its boot process (for IOS28 and newer).
//
// This works in a slightly different way on a real console: older IOS versions (< IOS28) all
// have the same range (933E0000 - 93400000), thus they don't write it at boot and just inherit
// all values. However, the range has changed since IOS28. To make things work properly
// after a reload, newer IOSes always write the legacy range before loading an IOS kernel;
// the new IOS either updates the range (>= IOS28) or inherits it (< IOS28).
//
// We can skip this convoluted process and just write the correct range directly.
Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(target_imv->unknown_begin, ADDR_UNKNOWN_BEGIN);
Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END);
return true;
}
Memory::Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE);
Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
Memory::Write_U32(target_imv->mem1_end, ADDR_MEM1_END);
Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH1);
Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH2);
Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION);
Memory::Write_U32(PLACEHOLDER, ADDR_PH3);
Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
Memory::Write_U32(target_imv->ios_date, ADDR_IOS_DATE);
Memory::Write_U32(target_imv->unknown_begin, ADDR_UNKNOWN_BEGIN);
Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH4);
Memory::Write_U32(PLACEHOLDER, ADDR_PH5);
Memory::Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR);
Memory::Write_U8(0xDE, ADDR_BOOT_FLAG);
Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG);
Memory::Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION);
Memory::Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC);
return true;
}
void Kernel::AddDevice(std::unique_ptr<Device::Device> device)
{
_assert_(device->GetDeviceType() == Device::Device::DeviceType::Static);
m_device_map[device->GetDeviceName()] = std::move(device);
}
void Kernel::AddStaticDevices()
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
_assert_msg_(IOS, m_device_map.empty(), "Reinit called while already initialized");
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
AddDevice(std::make_unique<Device::BluetoothEmu>(*this, "/dev/usb/oh1/57e/305"));
else
AddDevice(std::make_unique<Device::BluetoothReal>(*this, "/dev/usb/oh1/57e/305"));
AddDevice(std::make_unique<Device::STMImmediate>(*this, "/dev/stm/immediate"));
AddDevice(std::make_unique<Device::STMEventHook>(*this, "/dev/stm/eventhook"));
AddDevice(std::make_unique<Device::FS>(*this, "/dev/fs"));
AddDevice(std::make_unique<Device::ES>(*this, "/dev/es"));
AddDevice(std::make_unique<Device::DI>(*this, "/dev/di"));
AddDevice(std::make_unique<Device::NetKDRequest>(*this, "/dev/net/kd/request"));
AddDevice(std::make_unique<Device::NetKDTime>(*this, "/dev/net/kd/time"));
AddDevice(std::make_unique<Device::NetNCDManage>(*this, "/dev/net/ncd/manage"));
AddDevice(std::make_unique<Device::NetWDCommand>(*this, "/dev/net/wd/command"));
AddDevice(std::make_unique<Device::NetIPTop>(*this, "/dev/net/ip/top"));
AddDevice(std::make_unique<Device::NetSSL>(*this, "/dev/net/ssl"));
AddDevice(std::make_unique<Device::USB_KBD>(*this, "/dev/usb/kbd"));
AddDevice(std::make_unique<Device::SDIOSlot0>(*this, "/dev/sdio/slot0"));
AddDevice(std::make_unique<Device::Stub>(*this, "/dev/sdio/slot1"));
AddDevice(std::make_unique<Device::USB_HIDv4>(*this, "/dev/usb/hid"));
AddDevice(std::make_unique<Device::OH0>(*this, "/dev/usb/oh0"));
AddDevice(std::make_unique<Device::Stub>(*this, "/dev/usb/oh1"));
AddDevice(std::make_unique<Device::USB_VEN>(*this, "/dev/usb/ven"));
AddDevice(std::make_unique<Device::WFSSRV>(*this, "/dev/usb/wfssrv"));
AddDevice(std::make_unique<Device::WFSI>(*this, "/dev/wfsi"));
}
// IOS used by the latest System Menu (4.3).
constexpr u64 IOS80_TITLE_ID = 0x0000000100000050;
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
Kernel::Kernel(u64 title_id) : m_title_id(title_id)
{
INFO_LOG(IOS, "Starting IOS %016" PRIx64, title_id);
if (!SetupMemory(title_id, MemorySetupType::IOSReload))
WARN_LOG(IOS, "No information about this IOS -- cannot set up memory values");
if (title_id == MIOS_TITLE_ID)
{
MIOS::Load();
return;
}
// IOS re-inits IPC and sends a dummy ack during its boot process.
EnqueueIPCAcknowledgement(0);
AddStaticDevices();
}
Kernel::~Kernel()
{
CoreTiming::RemoveAllEvents(s_event_enqueue);
// Close all devices that were opened
for (auto& device : m_fdmap)
{
if (!device)
continue;
device->Close(0);
}
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
m_device_map.clear();
}
}
void Kernel::HandleIPCEvent(u64 userdata)
{
if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG)
m_ack_queue.push_back(static_cast<u32>(userdata));
else if (userdata & ENQUEUE_REQUEST_FLAG)
m_request_queue.push_back(static_cast<u32>(userdata));
else
m_reply_queue.push_back(static_cast<u32>(userdata));
UpdateIPC();
}
void Init()
{
s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", [](u64 userdata, s64) {
if (s_ios)
s_ios->HandleIPCEvent(userdata);
});
s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", [](u64, s64) {
if (!s_ios)
return;
auto device = static_cast<Device::SDIOSlot0*>(s_ios->GetDeviceByName("/dev/sdio/slot0").get());
if (device)
device->EventNotify();
});
// Start with IOS80 to simulate part of the Wii boot process.
s_ios = std::make_unique<Kernel>(IOS80_TITLE_ID);
// On a Wii, boot2 launches the system menu IOS, which then launches the system menu
// (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up.
// This means that the constants in the 0x3100 region are always set up by the time
// a game is launched. This is necessary because booting games from the game list skips
// a significant part of a Wii's boot process.
SetupMemory(IOS80_TITLE_ID, MemorySetupType::Full);
}
void Shutdown()
{
s_ios.reset();
}
Kernel* GetIOS()
{
return s_ios.get();
}
// Similar to syscall 0x42 (ios_boot); this is used to change the current active IOS.
// IOS writes the new version to 0x3140 before restarting, but it does *not* poke any
// of the other constants to the memory.
bool Kernel::BootIOS(const u64 ios_title_id)
{
// A real Wii goes through several steps before getting to MIOS.
//
// * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game.
// * BC (similar to boot1) lowers the clock speed to the Flipper's and then launches boot2.
// * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu.
//
// Because we currently don't have boot1 and boot2, and BC is only ever used to launch MIOS
// (indirectly via boot2), we can just launch MIOS when BC is launched.
if (ios_title_id == BC_TITLE_ID)
{
NOTICE_LOG(IOS, "BC: Launching MIOS...");
return BootIOS(MIOS_TITLE_ID);
}
// Shut down the active IOS first before switching to the new one.
s_ios.reset();
s_ios = std::make_unique<Kernel>(ios_title_id);
return true;
}
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
void Kernel::SetUidForPPC(u32 uid)
{
m_ppc_uid = uid;
}
u32 Kernel::GetUidForPPC() const
{
return m_ppc_uid;
}
void Kernel::SetGidForPPC(u16 gid)
{
m_ppc_gid = gid;
}
u16 Kernel::GetGidForPPC() const
{
return m_ppc_gid;
}
// This corresponds to syscall 0x41, which loads a binary from the NAND and bootstraps the PPC.
// Unlike 0x42, IOS will set up some constants in memory before booting the PPC.
bool Kernel::BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader)
{
if (!content_loader.IsValid())
return false;
const auto* content = content_loader.GetContentByIndex(content_loader.GetTMD().GetBootIndex());
if (!content)
return false;
const auto dol_loader = std::make_unique<CDolLoader>(content->m_Data->Get());
if (!dol_loader->IsValid())
return false;
if (!SetupMemory(m_title_id, MemorySetupType::Full))
return false;
dol_loader->Load();
// NAND titles start with address translation off at 0x3400 (via the PPC bootstub)
// The state of other CPU registers (like the BAT registers) doesn't matter much
// because the realmode code at 0x3400 initializes everything itself anyway.
MSR = 0;
PC = 0x3400;
return true;
}
void Kernel::SDIO_EventNotify()
{
// TODO: Potential race condition: If IsRunning() becomes false after
// it's checked, an event may be scheduled after CoreTiming shuts down.
if (SConfig::GetInstance().bWii && Core::IsRunning())
CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU);
}
s32 Kernel::GetFreeDeviceID()
{
for (u32 i = 0; i < IPC_MAX_FDS; i++)
{
if (m_fdmap[i] == nullptr)
{
return i;
}
}
return -1;
}
std::shared_ptr<Device::Device> Kernel::GetDeviceByName(const std::string& device_name)
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
const auto iterator = m_device_map.find(device_name);
return iterator != m_device_map.end() ? iterator->second : nullptr;
}
void Kernel::DoState(PointerWrap& p)
{
p.Do(m_request_queue);
p.Do(m_reply_queue);
p.Do(m_last_reply_time);
p.Do(m_title_id);
p.Do(m_ppc_uid);
p.Do(m_ppc_gid);
if (m_title_id == MIOS_TITLE_ID)
return;
// We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can
// successfully save or re-create /tmp
for (auto& descriptor : m_fdmap)
{
if (descriptor)
descriptor->PrepareForState(p.GetMode());
}
for (const auto& entry : m_device_map)
entry.second->DoState(p);
if (p.GetMode() == PointerWrap::MODE_READ)
{
for (u32 i = 0; i < IPC_MAX_FDS; i++)
{
u32 exists = 0;
p.Do(exists);
if (exists)
{
auto device_type = Device::Device::DeviceType::Static;
p.Do(device_type);
switch (device_type)
{
case Device::Device::DeviceType::Static:
{
std::string device_name;
p.Do(device_name);
m_fdmap[i] = GetDeviceByName(device_name);
break;
}
case Device::Device::DeviceType::FileIO:
m_fdmap[i] = std::make_shared<Device::FileIO>(*this, "");
m_fdmap[i]->DoState(p);
break;
case Device::Device::DeviceType::OH0:
m_fdmap[i] = std::make_shared<Device::OH0Device>(*this, "");
m_fdmap[i]->DoState(p);
break;
}
}
}
}
else
{
for (auto& descriptor : m_fdmap)
{
u32 exists = descriptor ? 1 : 0;
p.Do(exists);
if (exists)
{
auto device_type = descriptor->GetDeviceType();
p.Do(device_type);
if (device_type == Device::Device::DeviceType::Static)
{
std::string device_name = descriptor->GetDeviceName();
p.Do(device_name);
}
else
{
descriptor->DoState(p);
}
}
}
}
}
// Returns the FD for the newly opened device (on success) or an error code.
s32 Kernel::OpenDevice(OpenRequest& request)
{
const s32 new_fd = GetFreeDeviceID();
INFO_LOG(IOS, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd);
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
{
ERROR_LOG(IOS, "Couldn't get a free fd, too many open files");
return FS_EFDEXHAUSTED;
}
request.fd = new_fd;
std::shared_ptr<Device::Device> device;
if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path))
{
device = std::make_shared<Device::OH0Device>(*this, request.path);
}
else if (request.path.find("/dev/") == 0)
{
device = GetDeviceByName(request.path);
}
else if (request.path.find('/') == 0)
{
device = std::make_shared<Device::FileIO>(*this, request.path);
}
if (!device)
{
ERROR_LOG(IOS, "Unknown device: %s", request.path.c_str());
return IPC_ENOENT;
}
const ReturnCode code = device->Open(request);
if (code < IPC_SUCCESS)
return code;
m_fdmap[new_fd] = device;
return new_fd;
}
IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
{
if (request.command == IPC_CMD_OPEN)
{
OpenRequest open_request{request.address};
const s32 new_fd = OpenDevice(open_request);
return Device::Device::GetDefaultReply(new_fd);
}
const auto device = (request.fd < IPC_MAX_FDS) ? m_fdmap[request.fd] : nullptr;
if (!device)
return Device::Device::GetDefaultReply(IPC_EINVAL);
switch (request.command)
{
case IPC_CMD_CLOSE:
m_fdmap[request.fd].reset();
return Device::Device::GetDefaultReply(device->Close(request.fd));
case IPC_CMD_READ:
return device->Read(ReadWriteRequest{request.address});
case IPC_CMD_WRITE:
return device->Write(ReadWriteRequest{request.address});
case IPC_CMD_SEEK:
return device->Seek(SeekRequest{request.address});
case IPC_CMD_IOCTL:
return device->IOCtl(IOCtlRequest{request.address});
case IPC_CMD_IOCTLV:
return device->IOCtlV(IOCtlVRequest{request.address});
default:
_assert_msg_(IOS, false, "Unexpected command: %x", request.command);
return Device::Device::GetDefaultReply(IPC_EINVAL);
}
}
void Kernel::ExecuteIPCCommand(const u32 address)
{
Request request{address};
IPCCommandResult result = HandleIPCCommand(request);
if (!result.send_reply)
return;
// Ensure replies happen in order
const s64 ticks_until_last_reply = m_last_reply_time - CoreTiming::GetTicks();
if (ticks_until_last_reply > 0)
result.reply_delay_ticks += ticks_until_last_reply;
m_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
EnqueueIPCReply(request, result.return_value, static_cast<int>(result.reply_delay_ticks));
}
// Happens AS SOON AS IPC gets a new pointer!
void Kernel::EnqueueIPCRequest(u32 address)
{
CoreTiming::ScheduleEvent(1000, s_event_enqueue, address | ENQUEUE_REQUEST_FLAG);
}
// Called to send a reply to an IOS syscall
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, int cycles_in_future,
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.
Memory::Write_U32(request.command, request.address + 8);
// IOS also overwrites the command type with the reply type.
Memory::Write_U32(IPC_REPLY, request.address);
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from);
}
void Kernel::EnqueueIPCAcknowledgement(u32 address, int cycles_in_future)
{
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue,
address | ENQUEUE_ACKNOWLEDGEMENT_FLAG);
}
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
// Takes care of routing ipc <-> ipc HLE
void Kernel::UpdateIPC()
{
if (!IsReady())
return;
if (m_request_queue.size())
{
GenerateAck(m_request_queue.front());
u32 command = m_request_queue.front();
m_request_queue.pop_front();
ExecuteIPCCommand(command);
return;
}
if (m_reply_queue.size())
{
GenerateReply(m_reply_queue.front());
DEBUG_LOG(IOS, "<<-- Reply to IPC Request @ 0x%08x", m_reply_queue.front());
m_reply_queue.pop_front();
return;
}
if (m_ack_queue.size())
{
GenerateAck(m_ack_queue.front());
WARN_LOG(IOS, "<<-- Double-ack to IPC Request @ 0x%08x", m_ack_queue.front());
m_ack_queue.pop_front();
return;
}
}
void Kernel::UpdateDevices()
{
// Check if a hardware device must be updated
for (const auto& entry : m_device_map)
{
if (entry.second->IsOpened())
{
entry.second->Update();
}
}
}
void Kernel::UpdateWantDeterminism(const bool new_want_determinism)
{
WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism);
for (const auto& device : m_device_map)
device.second->UpdateWantDeterminism(new_want_determinism);
}
} // namespace HLE
} // namespace IOS

120
Source/Core/Core/IOS/IOS.h Normal file
View File

@ -0,0 +1,120 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <deque>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/CoreTiming.h"
#include "Core/HW/SystemTimers.h"
class PointerWrap;
namespace DiscIO
{
class CNANDContentLoader;
}
namespace IOS
{
namespace HLE
{
namespace Device
{
class Device;
}
struct Request;
struct OpenRequest;
struct IPCCommandResult
{
s32 return_value;
bool send_reply;
u64 reply_delay_ticks;
};
enum IPCCommandType : u32
{
IPC_CMD_OPEN = 1,
IPC_CMD_CLOSE = 2,
IPC_CMD_READ = 3,
IPC_CMD_WRITE = 4,
IPC_CMD_SEEK = 5,
IPC_CMD_IOCTL = 6,
IPC_CMD_IOCTLV = 7,
// This is used for replies to commands.
IPC_REPLY = 8,
};
// HLE for the IOS kernel: IPC, device management, syscalls, and Dolphin-specific, IOS-wide calls.
class Kernel
{
public:
explicit Kernel(u64 ios_title_id);
~Kernel();
void DoState(PointerWrap& p);
void HandleIPCEvent(u64 userdata);
void UpdateIPC();
void UpdateDevices();
void UpdateWantDeterminism(bool new_want_determinism);
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
void SDIO_EventNotify();
void EnqueueIPCRequest(u32 address);
void EnqueueIPCReply(const Request& request, s32 return_value, int cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
void SetUidForPPC(u32 uid);
u32 GetUidForPPC() const;
void SetGidForPPC(u16 gid);
u16 GetGidForPPC() const;
bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader);
bool BootIOS(u64 ios_title_id);
u32 GetVersion() const;
private:
void ExecuteIPCCommand(u32 address);
IPCCommandResult HandleIPCCommand(const Request& request);
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
void AddDevice(std::unique_ptr<Device::Device> device);
void AddStaticDevices();
s32 GetFreeDeviceID();
s32 OpenDevice(OpenRequest& request);
u64 m_title_id = 0;
static constexpr u8 IPC_MAX_FDS = 0x18;
std::map<std::string, std::shared_ptr<Device::Device>> m_device_map;
std::mutex m_device_map_mutex;
// TODO: make this fdmap per process.
std::array<std::shared_ptr<Device::Device>, IPC_MAX_FDS> m_fdmap;
u32 m_ppc_uid = 0;
u16 m_ppc_gid = 0;
using IPCMsgQueue = std::deque<u32>;
IPCMsgQueue m_request_queue; // ppc -> arm
IPCMsgQueue m_reply_queue; // arm -> ppc
IPCMsgQueue m_ack_queue; // arm -> ppc
u64 m_last_reply_time = 0;
};
// Used for controlling and accessing an IOS instance that is tied to emulation.
void Init();
void Shutdown();
Kernel* GetIOS();
} // namespace HLE
} // namespace IOS

File diff suppressed because it is too large Load Diff

View File

@ -1,92 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/CoreTiming.h"
#include "Core/HW/SystemTimers.h"
class PointerWrap;
namespace DiscIO
{
class CNANDContentLoader;
}
namespace IOS
{
namespace HLE
{
namespace Device
{
class Device;
}
struct Request;
struct IPCCommandResult
{
s32 return_value;
bool send_reply;
u64 reply_delay_ticks;
};
enum IPCCommandType : u32
{
IPC_CMD_OPEN = 1,
IPC_CMD_CLOSE = 2,
IPC_CMD_READ = 3,
IPC_CMD_WRITE = 4,
IPC_CMD_SEEK = 5,
IPC_CMD_IOCTL = 6,
IPC_CMD_IOCTLV = 7,
// This is used for replies to commands.
IPC_REPLY = 8,
};
// Init events and devices
void Init();
// Shutdown
void Shutdown();
// Reload IOS (to a possibly different version); write the new version to 0x3140 and set up devices.
bool Reload(u64 ios_title_id);
u32 GetVersion();
void SetUIDForPPC(u32 uid);
u32 GetUIDForPPC();
void SetGIDForPPC(u16 gid);
u16 GetGIDForPPC();
bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader);
// Do State
void DoState(PointerWrap& p);
void SDIO_EventNotify();
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
std::shared_ptr<Device::Device> AccessDeviceByID(u32 id);
// Update
void Update();
// Update Devices
void UpdateDevices();
void UpdateWantDeterminism(bool new_want_determinism);
void ExecuteCommand(u32 address);
void EnqueueRequest(u32 address);
void EnqueueReply(const Request& request, s32 return_value, int cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
} // namespace HLE
} // namespace IOS

View File

@ -0,0 +1,329 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/IOS/MemoryValues.h"
#include "Common/CommonTypes.h"
namespace IOS
{
namespace HLE
{
constexpr u32 MEM1_SIZE = 0x01800000;
constexpr u32 MEM1_END = 0x81800000;
constexpr u32 MEM1_ARENA_BEGIN = 0x00000000;
constexpr u32 MEM1_ARENA_END = 0x81800000;
constexpr u32 MEM2_SIZE = 0x4000000;
constexpr u32 MEM2_ARENA_BEGIN = 0x90000800;
constexpr u32 HOLLYWOOD_REVISION = 0x00000011;
constexpr u32 PLACEHOLDER = 0xDEADBEEF;
constexpr u32 RAM_VENDOR = 0x0000FF01;
constexpr u32 RAM_VENDOR_MIOS = 0xCAFEBABE;
// These values were manually extracted from the relevant IOS binaries.
// The writes are usually contained in a single function that
// mostly writes raw literals to the relevant locations.
// e.g. IOS9, version 1034, content id 0x00000006, function at 0xffff6884
constexpr std::array<MemoryValues, 40> ios_memory_values = {
{{
9, 0x9040a, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
11, 0xb000a, 0x102506, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
12, 0xc020e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
13, 0xd0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
14, 0xe0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
15, 0xf0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
17, 0x110408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
20, 0x14000c, 0x102506, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
21, 0x15040f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
22, 0x16050e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
28, 0x1c070f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93800000, MEM2_ARENA_BEGIN,
0x937E0000, 0x937E0000, 0x93800000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93800000, 0x93820000, 0,
},
{
30, 0x1e0a10, 0x40308, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
31, 0x1f0e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
33, 0x210e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
34, 0x220e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
35, 0x230e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
36, 0x240e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
37, 0x25161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
38, 0x26101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
40, 0x280911, 0x022308, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
41, 0x290e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
43, 0x2b0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
45, 0x2d0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
46, 0x2e0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
48, 0x30101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
50, 0x321319, 0x101008, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
51, 0x331219, 0x071108, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
52, 0x34161d, 0x101008, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
53, 0x35161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
55, 0x37161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
56, 0x38161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
57, 0x39171f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
58, 0x3a1820, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
59, 0x3b1c21, 0x101811, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
60, 0x3c181e, 0x112408, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
61, 0x3d161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
62, 0x3e191e, 0x022712, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
70, 0x461a1f, 0x060309, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
80, 0x501b20, 0x030310, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
257,
0x707,
0x82209,
MEM1_SIZE,
MEM1_SIZE,
MEM1_END,
MEM1_ARENA_BEGIN,
MEM1_ARENA_END,
MEM2_SIZE,
MEM2_SIZE,
0x93600000,
MEM2_ARENA_BEGIN,
0x935E0000,
0x935E0000,
0x93600000,
HOLLYWOOD_REVISION,
RAM_VENDOR_MIOS,
PLACEHOLDER,
PLACEHOLDER,
PLACEHOLDER,
}}};
const std::array<MemoryValues, 40>& GetMemoryValues()
{
return ios_memory_values;
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <array>
#include "Common/CommonTypes.h"
namespace IOS
{
namespace HLE
{
struct MemoryValues
{
u16 ios_number;
u32 ios_version;
u32 ios_date;
u32 mem1_physical_size;
u32 mem1_simulated_size;
u32 mem1_end;
u32 mem1_arena_begin;
u32 mem1_arena_end;
u32 mem2_physical_size;
u32 mem2_simulated_size;
u32 mem2_end;
u32 mem2_arena_begin;
u32 mem2_arena_end;
u32 ipc_buffer_begin;
u32 ipc_buffer_end;
u32 hollywood_revision;
u32 ram_vendor;
u32 unknown_begin;
u32 unknown_end;
u32 sysmenu_sync;
};
const std::array<MemoryValues, 40>& GetMemoryValues();
}
}

View File

@ -61,7 +61,7 @@ namespace HLE
{
namespace Device
{
NetIPTop::NetIPTop(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
NetIPTop::NetIPTop(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
#ifdef _WIN32
int ret = WSAStartup(MAKEWORD(2, 2), &InitData);

View File

@ -61,7 +61,7 @@ namespace Device
class NetIPTop : public Device
{
public:
NetIPTop(u32 device_id, const std::string& device_name);
NetIPTop(Kernel& ios, const std::string& device_name);
virtual ~NetIPTop();
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -24,8 +24,7 @@ namespace HLE
{
namespace Device
{
NetKDRequest::NetKDRequest(u32 device_id, const std::string& device_name)
: Device(device_id, device_name)
NetKDRequest::NetKDRequest(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -22,7 +22,7 @@ namespace Device
class NetKDRequest : public Device
{
public:
NetKDRequest(u32 device_id, const std::string& device_name);
NetKDRequest(Kernel& ios, const std::string& device_name);
~NetKDRequest() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -16,7 +16,7 @@ namespace HLE
{
namespace Device
{
NetKDTime::NetKDTime(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
NetKDTime::NetKDTime(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -18,7 +18,7 @@ namespace Device
class NetKDTime : public Device
{
public:
NetKDTime(u32 device_id, const std::string& device_name);
NetKDTime(Kernel& ios, const std::string& device_name);
~NetKDTime() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -19,8 +19,7 @@ namespace HLE
{
namespace Device
{
NetNCDManage::NetNCDManage(u32 device_id, const std::string& device_name)
: Device(device_id, device_name)
NetNCDManage::NetNCDManage(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -20,7 +20,7 @@ namespace Device
class NetNCDManage : public Device
{
public:
NetNCDManage(u32 device_id, const std::string& device_name);
NetNCDManage(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;

View File

@ -37,7 +37,7 @@ static constexpr mbedtls_x509_crt_profile mbedtls_x509_crt_profile_wii = {
0, /* No RSA min key size */
};
NetSSL::NetSSL(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
NetSSL::NetSSL(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
for (WII_SSL& ssl : _SSL)
{

View File

@ -19,7 +19,7 @@
// clang-format on
#include "Common/CommonTypes.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Device.h"
namespace IOS
@ -90,7 +90,7 @@ namespace Device
class NetSSL : public Device
{
public:
NetSSL(u32 device_id, const std::string& device_name);
NetSSL(Kernel& ios, const std::string& device_name);
virtual ~NetSSL();

View File

@ -16,7 +16,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Network/Socket.h" // No Wii socket support while using NetPlay or TAS
#ifdef _WIN32
@ -579,7 +579,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
it->is_ssl ? (int)it->ssl_type : (int)it->net_type, ReturnValue, nonBlock,
forceNonBlock);
EnqueueReply(it->request, ReturnValue);
// TODO: remove the dependency on a running IOS instance.
GetIOS()->EnqueueIPCReply(it->request, ReturnValue);
it = pending_sockops.erase(it);
}
else

View File

@ -52,7 +52,7 @@ typedef struct pollfd pollfd_t;
#include "Common/Logging/Log.h"
#include "Common/NonCopyable.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Network/IP/Top.h"
#include "Core/IOS/Network/SSL.h"
@ -234,7 +234,7 @@ public:
{
ERROR_LOG(IOS_NET, "DoSock: Error, fd not found (%08x, %08X, %08X)", sock, request.address,
type);
EnqueueReply(request, -SO_EBADF);
GetIOS()->EnqueueIPCReply(request, -SO_EBADF);
}
else
{

View File

@ -21,8 +21,7 @@ namespace HLE
{
namespace Device
{
NetWDCommand::NetWDCommand(u32 device_id, const std::string& device_name)
: Device(device_id, device_name)
NetWDCommand::NetWDCommand(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -18,7 +18,7 @@ namespace Device
class NetWDCommand : public Device
{
public:
NetWDCommand(u32 device_id, const std::string& device_name);
NetWDCommand(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;

View File

@ -14,7 +14,7 @@
#include "Common/SDCardUtil.h"
#include "Core/ConfigManager.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/SDIO/SDIOSlot0.h"
namespace IOS
@ -23,7 +23,7 @@ namespace HLE
{
namespace Device
{
SDIOSlot0::SDIOSlot0(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
SDIOSlot0::SDIOSlot0(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}
@ -49,7 +49,7 @@ void SDIOSlot0::EventNotify()
if ((SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_INSERT) ||
(!SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_REMOVE))
{
EnqueueReply(m_event->request, m_event->type);
m_ios.EnqueueIPCReply(m_event->request, m_event->type);
m_event.reset();
}
}
@ -302,7 +302,7 @@ u32 SDIOSlot0::ExecuteCommand(const Request& request, u32 _BufferIn, u32 _Buffer
// release returns 0
// unknown sd int
// technically we do it out of order, oh well
EnqueueReply(m_event->request, EVENT_INVALID);
m_ios.EnqueueIPCReply(m_event->request, EVENT_INVALID);
m_event.reset();
break;
}

View File

@ -12,7 +12,7 @@
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -26,7 +26,7 @@ namespace Device
class SDIOSlot0 : public Device
{
public:
SDIOSlot0(u32 device_id, const std::string& device_name);
SDIOSlot0(Kernel& ios, const std::string& device_name);
void DoState(PointerWrap& p) override;

View File

@ -39,7 +39,7 @@ IPCCommandResult STMImmediate::IOCtl(const IOCtlRequest& request)
break;
}
Memory::Write_U32(0, s_event_hook_request->buffer_out);
EnqueueReply(*s_event_hook_request, IPC_SUCCESS);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
break;
@ -109,7 +109,7 @@ void STMEventHook::TriggerEvent(const u32 event) const
return;
Memory::Write_U32(event, s_event_hook_request->buffer_out);
EnqueueReply(*s_event_hook_request, IPC_SUCCESS);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
}

View File

@ -8,7 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -46,7 +46,7 @@ namespace Device
class STMImmediate final : public Device
{
public:
STMImmediate(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {}
using Device::Device;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
};
@ -54,7 +54,7 @@ public:
class STMEventHook final : public Device
{
public:
STMEventHook(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {}
using Device::Device;
ReturnCode Close(u32 fd) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
void DoState(PointerWrap& p) override;

View File

@ -9,7 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
class SysConf;
@ -26,7 +26,7 @@ namespace Device
class BluetoothBase : public Device
{
public:
BluetoothBase(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {}
using Device::Device;
virtual void UpdateSyncButtonState(bool is_held) {}
virtual void TriggerSyncButtonPressedEvent() {}
virtual void TriggerSyncButtonHeldEvent() {}

View File

@ -23,7 +23,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
@ -39,8 +39,8 @@ SQueuedEvent::SQueuedEvent(u32 size, u16 handle) : m_size(size), m_connectionHan
namespace Device
{
BluetoothEmu::BluetoothEmu(u32 device_id, const std::string& device_name)
: BluetoothBase(device_id, device_name)
BluetoothEmu::BluetoothEmu(Kernel& ios, const std::string& device_name)
: BluetoothBase(ios, device_name)
{
SysConf sysconf{Core::WantsDeterminism() ? Common::FromWhichRoot::FROM_SESSION_ROOT :
Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
@ -105,14 +105,14 @@ BluetoothEmu::~BluetoothEmu()
}
template <typename T>
static void DoStateForMessage(PointerWrap& p, std::unique_ptr<T>& message)
static void DoStateForMessage(Kernel& ios, 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)
{
IOCtlVRequest request{request_address};
message = std::make_unique<T>(request);
message = std::make_unique<T>(ios, request);
}
}
@ -129,9 +129,9 @@ void BluetoothEmu::DoState(PointerWrap& p)
p.Do(m_is_active);
p.Do(m_ControllerBD);
DoStateForMessage(p, m_CtrlSetup);
DoStateForMessage(p, m_HCIEndpoint);
DoStateForMessage(p, m_ACLEndpoint);
DoStateForMessage(m_ios, p, m_CtrlSetup);
DoStateForMessage(m_ios, p, m_HCIEndpoint);
DoStateForMessage(m_ios, p, m_ACLEndpoint);
p.Do(m_last_ticks);
p.DoArray(m_PacketCount);
p.Do(m_ScanEnable);
@ -166,7 +166,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
{
case USB::IOCTLV_USBV0_CTRLMSG: // HCI command is received from the stack
{
m_CtrlSetup = std::make_unique<USB::V0CtrlMessage>(request);
m_CtrlSetup = std::make_unique<USB::V0CtrlMessage>(m_ios, request);
// Replies are generated inside
ExecuteHCICommandMessage(*m_CtrlSetup);
m_CtrlSetup.reset();
@ -176,7 +176,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_BLKMSG:
{
const USB::V0BulkMessage ctrl{request};
const USB::V0BulkMessage ctrl{m_ios, request};
switch (ctrl.endpoint)
{
case ACL_DATA_OUT: // ACL data is received from the stack
@ -195,7 +195,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
}
case ACL_DATA_IN: // We are given an ACL buffer to fill
{
m_ACLEndpoint = std::make_unique<USB::V0BulkMessage>(request);
m_ACLEndpoint = std::make_unique<USB::V0BulkMessage>(m_ios, request);
DEBUG_LOG(IOS_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address);
send_reply = false;
break;
@ -208,10 +208,10 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_INTRMSG:
{
const USB::V0IntrMessage ctrl{request};
const USB::V0IntrMessage ctrl{m_ios, request};
if (ctrl.endpoint == HCI_EVENT) // We are given a HCI buffer to fill
{
m_HCIEndpoint = std::make_unique<USB::V0IntrMessage>(request);
m_HCIEndpoint = std::make_unique<USB::V0IntrMessage>(m_ios, request);
DEBUG_LOG(IOS_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address);
send_reply = false;
}
@ -265,7 +265,7 @@ void BluetoothEmu::SendACLPacket(u16 connection_handle, const u8* data, u32 size
// Write the packet to the buffer
memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
EnqueueReply(m_ACLEndpoint->ios_request, sizeof(hci_acldata_hdr_t) + size);
m_ios.EnqueueIPCReply(m_ACLEndpoint->ios_request, sizeof(hci_acldata_hdr_t) + size);
m_ACLEndpoint.reset();
}
else
@ -293,7 +293,7 @@ void BluetoothEmu::AddEventToQueue(const SQueuedEvent& _event)
m_HCIEndpoint->FillBuffer(_event.m_buffer, _event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint->ios_request, _event.m_size);
m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, _event.m_size);
m_HCIEndpoint.reset();
}
else // push new one, pop oldest
@ -309,7 +309,7 @@ void BluetoothEmu::AddEventToQueue(const SQueuedEvent& _event)
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint->ios_request, event.m_size);
m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, event.m_size);
m_HCIEndpoint.reset();
m_EventQueue.pop_front();
}
@ -335,7 +335,7 @@ void BluetoothEmu::Update()
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint->ios_request, event.m_size);
m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, event.m_size);
m_HCIEndpoint.reset();
m_EventQueue.pop_front();
}
@ -430,7 +430,7 @@ void BluetoothEmu::ACLPool::WriteToEndpoint(USB::V0BulkMessage& endpoint)
m_queue.pop_front();
EnqueueReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size);
m_ios.EnqueueIPCReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size);
}
bool BluetoothEmu::SendEventInquiryComplete()
@ -1141,7 +1141,7 @@ void BluetoothEmu::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_messa
}
// HCI command is finished, send a reply to command
EnqueueReply(ctrl_message.ios_request, ctrl_message.length);
m_ios.EnqueueIPCReply(ctrl_message.ios_request, ctrl_message.length);
}
//

View File

@ -14,7 +14,7 @@
#include "Common/CommonTypes.h"
#include "Core/HW/Wiimote.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
#include "Core/IOS/USB/Bluetooth/hci.h"
@ -45,7 +45,7 @@ namespace Device
class BluetoothEmu final : public BluetoothBase
{
public:
BluetoothEmu(u32 device_id, const std::string& device_name);
BluetoothEmu(Kernel& ios, const std::string& device_name);
virtual ~BluetoothEmu();
@ -78,17 +78,8 @@ private:
class ACLPool
{
struct Packet
{
u8 data[ACL_PKT_SIZE];
u16 size;
u16 conn_handle;
};
std::deque<Packet> m_queue;
public:
ACLPool() : m_queue() {}
explicit ACLPool(Kernel& ios) : m_ios(ios), m_queue() {}
void Store(const u8* data, const u16 size, const u16 conn_handle);
void WriteToEndpoint(USB::V0BulkMessage& endpoint);
@ -96,7 +87,17 @@ private:
bool IsEmpty() const { return m_queue.empty(); }
// For SaveStates
void DoState(PointerWrap& p) { p.Do(m_queue); }
} m_acl_pool;
private:
struct Packet
{
u8 data[ACL_PKT_SIZE];
u16 size;
u16 conn_handle;
};
Kernel& m_ios;
std::deque<Packet> m_queue;
} m_acl_pool{m_ios};
u32 m_PacketCount[MAX_BBMOTES] = {};
u64 m_last_ticks = 0;

View File

@ -56,8 +56,8 @@ static bool IsBluetoothDevice(const libusb_interface_descriptor& descriptor)
namespace Device
{
BluetoothReal::BluetoothReal(u32 device_id, const std::string& device_name)
: BluetoothBase(device_id, device_name)
BluetoothReal::BluetoothReal(Kernel& ios, const std::string& device_name)
: BluetoothBase(ios, device_name)
{
const int ret = libusb_init(&m_libusb_context);
if (ret < 0)
@ -179,7 +179,7 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_CTRLMSG:
{
std::lock_guard<std::mutex> lk(m_transfers_mutex);
auto cmd = std::make_unique<USB::V0CtrlMessage>(request);
auto cmd = std::make_unique<USB::V0CtrlMessage>(m_ios, request);
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->data_address));
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
@ -228,7 +228,7 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_INTRMSG:
{
std::lock_guard<std::mutex> lk(m_transfers_mutex);
auto cmd = std::make_unique<USB::V0IntrMessage>(request);
auto cmd = std::make_unique<USB::V0IntrMessage>(m_ios, request);
if (request.request == USB::IOCTLV_USBV0_INTRMSG)
{
if (m_sync_button_state == SyncButtonState::Pressed)
@ -310,7 +310,7 @@ void BluetoothReal::DoState(PointerWrap& p)
// waiting for the previous request to complete. This is usually not an issue as long as
// the Bluetooth state is the same (same Wii remote connections).
for (const auto& address_to_discard : addresses_to_discard)
EnqueueReply(Request{address_to_discard}, 0);
m_ios.EnqueueIPCReply(Request{address_to_discard}, 0);
// Prevent the callbacks from replying to a request that has already been discarded.
m_current_transfers.clear();
@ -452,7 +452,7 @@ void BluetoothReal::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
hci_event.PacketIndicator = 0x01;
hci_event.Opcode = m_fake_vendor_command_reply_opcode;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event)));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event)));
}
// Due to how the widcomm stack which Nintendo uses is coded, we must never
@ -477,7 +477,7 @@ void BluetoothReal::FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl)
reply.max_sco_size = SCO_PKT_SIZE;
reply.num_sco_pkts = SCO_PKT_NUM;
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply));
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
}
void BluetoothReal::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload, const u8 size)
@ -488,7 +488,7 @@ void BluetoothReal::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payl
hci_event.length = size;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size);
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + size));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + size));
}
// When the red sync button is pressed, a HCI event is generated:
@ -638,7 +638,8 @@ void BluetoothReal::HandleCtrlTransfer(libusb_transfer* tr)
}
const auto& command = m_current_transfers.at(tr).command;
command->FillBuffer(libusb_control_transfer_get_data(tr), tr->actual_length);
EnqueueReply(command->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
m_ios.EnqueueIPCReply(command->ios_request, tr->actual_length, 0,
CoreTiming::FromThread::NON_CPU);
m_current_transfers.erase(tr);
}
@ -688,7 +689,8 @@ void BluetoothReal::HandleBulkOrIntrTransfer(libusb_transfer* tr)
const auto& command = m_current_transfers.at(tr).command;
command->FillBuffer(tr->buffer, tr->actual_length);
EnqueueReply(command->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
m_ios.EnqueueIPCReply(command->ios_request, tr->actual_length, 0,
CoreTiming::FromThread::NON_CPU);
m_current_transfers.erase(tr);
}
} // namespace Device

View File

@ -16,7 +16,7 @@
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Common/Timer.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/IOS/USB/USBV0.h"
@ -48,7 +48,7 @@ namespace Device
class BluetoothReal final : public BluetoothBase
{
public:
BluetoothReal(u32 device_id, const std::string& device_name);
BluetoothReal(Kernel& ios, const std::string& device_name);
~BluetoothReal() override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -7,7 +7,7 @@
#include <string>
#include "Common/CommonTypes.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
class PointerWrap;
@ -21,10 +21,7 @@ namespace Device
class BluetoothStub final : public BluetoothBase
{
public:
BluetoothStub(const u32 device_id, const std::string& device_name)
: BluetoothBase(device_id, device_name)
{
}
using BluetoothBase::BluetoothBase;
ReturnCode Open(const OpenRequest& request) override;
void DoState(PointerWrap& p) override;
};

View File

@ -932,7 +932,7 @@ void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _
DEBUG_LOG(WIIMOTE, " Channel: %x", _channelID);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
IOS::HLE::GetIOS()->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->m_WiiMotes[_number].ReceiveL2capData(_channelID, _pData, _Size);
}

View File

@ -33,6 +33,11 @@ void TransferCommand::FillBuffer(const u8* src, const size_t size) const
Memory::CopyToEmu(data_address, src, size);
}
void TransferCommand::OnTransferComplete(s32 return_value) const
{
m_ios.EnqueueIPCReply(ios_request, return_value, 0, CoreTiming::FromThread::NON_CPU);
}
void IsoMessage::SetPacketReturnValue(const size_t packet_num, const u16 return_value) const
{
Memory::Write_U16(return_value, static_cast<u32>(packet_sizes_addr + packet_num * sizeof(u16)));

View File

@ -100,15 +100,19 @@ struct TransferCommand
Request ios_request;
u32 data_address = 0;
TransferCommand(const Request& ios_request_, u32 data_address_)
: ios_request(ios_request_), data_address(data_address_)
TransferCommand(Kernel& ios, const Request& ios_request_, u32 data_address_)
: ios_request(ios_request_), data_address(data_address_), m_ios(ios)
{
}
virtual ~TransferCommand() = default;
// Called after a transfer has completed and before replying to the transfer request.
virtual void OnTransferComplete() const {}
// Called after a transfer has completed to reply to the IPC request.
// This can be overridden for additional processing before replying.
virtual void OnTransferComplete(s32 return_value) const;
std::unique_ptr<u8[]> MakeBuffer(size_t size) const;
void FillBuffer(const u8* src, size_t size) const;
private:
Kernel& m_ios;
};
struct CtrlMessage : TransferCommand

View File

@ -27,7 +27,7 @@ namespace HLE
{
namespace Device
{
USBHost::USBHost(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
USBHost::USBHost(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
#ifdef __LIBUSB__
const int ret = libusb_init(&m_libusb_context);
@ -150,7 +150,7 @@ bool USBHost::AddNewDevices(std::set<u64>& new_devices, DeviceChangeHooks& hooks
continue;
}
auto usb_device = std::make_unique<USB::LibusbDevice>(device, descriptor);
auto usb_device = std::make_unique<USB::LibusbDevice>(m_ios, device, descriptor);
if (!ShouldAddDevice(*usb_device))
{
libusb_unref_device(device);

View File

@ -17,7 +17,7 @@
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Common.h"
class PointerWrap;
@ -33,7 +33,7 @@ namespace Device
class USBHost : public Device
{
public:
USBHost(u32 device_id, const std::string& device_name);
USBHost(Kernel& ios, const std::string& device_name);
virtual ~USBHost();
ReturnCode Open(const OpenRequest& request) override;

View File

@ -15,7 +15,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/LibusbDevice.h"
namespace IOS
@ -24,8 +24,9 @@ namespace HLE
{
namespace USB
{
LibusbDevice::LibusbDevice(libusb_device* device, const libusb_device_descriptor& descriptor)
: m_device(device)
LibusbDevice::LibusbDevice(Kernel& ios, libusb_device* device,
const libusb_device_descriptor& descriptor)
: m_ios(ios), m_device(device)
{
libusb_ref_device(m_device);
m_vid = descriptor.idVendor;
@ -200,14 +201,14 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
}
const int ret = SetAltSetting(static_cast<u8>(cmd->value));
if (ret == 0)
EnqueueReply(cmd->ios_request, cmd->length);
m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length);
return ret;
}
case USBHDR(DIR_HOST2DEVICE, TYPE_STANDARD, REC_DEVICE, REQUEST_SET_CONFIGURATION):
{
const int ret = libusb_set_configuration(m_handle, cmd->value);
if (ret == 0)
EnqueueReply(cmd->ios_request, cmd->length);
m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length);
return ret;
}
}
@ -355,8 +356,7 @@ void LibusbDevice::TransferEndpoint::HandleTransfer(libusb_transfer* transfer,
return_value = IPC_ENOENT;
break;
}
cmd.OnTransferComplete();
EnqueueReply(cmd.ios_request, return_value, 0, CoreTiming::FromThread::NON_CPU);
cmd.OnTransferComplete(return_value);
m_transfers.erase(transfer);
}

View File

@ -43,7 +43,8 @@ private:
class LibusbDevice final : public Device
{
public:
LibusbDevice(libusb_device* device, const libusb_device_descriptor& device_descriptor);
LibusbDevice(Kernel& ios, libusb_device* device,
const libusb_device_descriptor& device_descriptor);
~LibusbDevice();
DeviceDescriptor GetDeviceDescriptor() const override;
std::vector<ConfigDescriptor> GetConfigurations() const override;
@ -61,6 +62,8 @@ public:
int SubmitTransfer(std::unique_ptr<IsoMessage> message) override;
private:
Kernel& m_ios;
std::vector<std::unique_ptr<LibusbConfigDescriptor>> m_config_descriptors;
u16 m_vid = 0;
u16 m_pid = 0;

View File

@ -25,7 +25,7 @@ namespace HLE
{
namespace Device
{
OH0::OH0(u32 device_id, const std::string& device_name) : USBHost(device_id, device_name)
OH0::OH0(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name)
{
}
@ -36,7 +36,7 @@ OH0::~OH0()
ReturnCode OH0::Open(const OpenRequest& request)
{
const u32 ios_major_version = GetVersion();
const u32 ios_major_version = m_ios.GetVersion();
if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59)
return IPC_EACCES;
return USBHost::Open(request);
@ -240,7 +240,7 @@ void OH0::TriggerHook(std::map<T, u32>& hooks, T value, const ReturnCode return_
const auto hook = hooks.find(value);
if (hook == hooks.end())
return;
EnqueueReply(Request{hook->second}, return_value, 0, CoreTiming::FromThread::ANY);
m_ios.EnqueueIPCReply(Request{hook->second}, return_value, 0, CoreTiming::FromThread::ANY);
hooks.erase(hook);
}
@ -325,26 +325,26 @@ s32 OH0::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
if (!ioctlv.HasNumberOfValidVectors(6, 1) ||
Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address)) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0CtrlMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V0CtrlMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV0_BLKMSG:
case USB::IOCTLV_USBV0_LBLKMSG:
if (!ioctlv.HasNumberOfValidVectors(2, 1) ||
Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(
std::make_unique<USB::V0BulkMessage>(ioctlv, ioctlv.request == USB::IOCTLV_USBV0_LBLKMSG));
return device.SubmitTransfer(std::make_unique<USB::V0BulkMessage>(
m_ios, ioctlv, ioctlv.request == USB::IOCTLV_USBV0_LBLKMSG));
case USB::IOCTLV_USBV0_INTRMSG:
if (!ioctlv.HasNumberOfValidVectors(2, 1) ||
Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0IntrMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V0IntrMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV0_ISOMSG:
if (!ioctlv.HasNumberOfValidVectors(3, 2))
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0IsoMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V0IsoMessage>(m_ios, ioctlv));
default:
return IPC_EINVAL;

View File

@ -38,7 +38,7 @@ namespace Device
class OH0 final : public USBHost
{
public:
OH0(u32 device_id, const std::string& device_name);
OH0(Kernel& ios, const std::string& device_name);
~OH0() override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -7,7 +7,7 @@
#include <vector>
#include "Common/ChunkFile.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/OH0/OH0.h"
#include "Core/IOS/USB/OH0/OH0Device.h"
@ -37,7 +37,7 @@ static void GetVidPidFromDevicePath(const std::string& device_path, u16& vid, u1
ss >> pid;
}
OH0Device::OH0Device(u32 id, const std::string& name) : Device(id, name, DeviceType::OH0)
OH0Device::OH0Device(Kernel& ios, const std::string& name) : Device(ios, name, DeviceType::OH0)
{
if (!name.empty())
GetVidPidFromDevicePath(name, m_vid, m_pid);
@ -45,7 +45,7 @@ OH0Device::OH0Device(u32 id, const std::string& name) : Device(id, name, DeviceT
void OH0Device::DoState(PointerWrap& p)
{
m_oh0 = std::static_pointer_cast<OH0>(GetDeviceByName("/dev/usb/oh0"));
m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
p.Do(m_name);
p.Do(m_vid);
p.Do(m_pid);
@ -54,14 +54,14 @@ void OH0Device::DoState(PointerWrap& p)
ReturnCode OH0Device::Open(const OpenRequest& request)
{
const u32 ios_major_version = GetVersion();
const u32 ios_major_version = m_ios.GetVersion();
if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59)
return IPC_ENOENT;
if (m_vid == 0 && m_pid == 0)
return IPC_ENOENT;
m_oh0 = std::static_pointer_cast<OH0>(GetDeviceByName("/dev/usb/oh0"));
m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
ReturnCode return_code;
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);

View File

@ -22,7 +22,7 @@ class OH0;
class OH0Device final : public Device
{
public:
OH0Device(u32 device_id, const std::string& device_name);
OH0Device(Kernel& ios, const std::string& device_name);
ReturnCode Open(const OpenRequest& request) override;
ReturnCode Close(u32 fd) override;

View File

@ -17,8 +17,8 @@ namespace HLE
{
namespace USB
{
V0CtrlMessage::V0CtrlMessage(const IOCtlVRequest& ioctlv)
: CtrlMessage(ioctlv, ioctlv.io_vectors[0].address)
V0CtrlMessage::V0CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: CtrlMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address);
request = Memory::Read_U8(ioctlv.in_vectors[1].address);
@ -27,8 +27,8 @@ V0CtrlMessage::V0CtrlMessage(const IOCtlVRequest& ioctlv)
length = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address));
}
V0BulkMessage::V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length)
: BulkMessage(ioctlv, ioctlv.io_vectors[0].address)
V0BulkMessage::V0BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv, bool long_length)
: BulkMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
if (long_length)
@ -37,15 +37,15 @@ V0BulkMessage::V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length)
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
}
V0IntrMessage::V0IntrMessage(const IOCtlVRequest& ioctlv)
: IntrMessage(ioctlv, ioctlv.io_vectors[0].address)
V0IntrMessage::V0IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IntrMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
}
V0IsoMessage::V0IsoMessage(const IOCtlVRequest& ioctlv)
: IsoMessage(ioctlv, ioctlv.io_vectors[1].address)
V0IsoMessage::V0IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IsoMessage(ios, ioctlv, ioctlv.io_vectors[1].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
length = Memory::Read_U16(ioctlv.in_vectors[1].address);

View File

@ -41,22 +41,22 @@ enum V0Requests
struct V0CtrlMessage final : CtrlMessage
{
explicit V0CtrlMessage(const IOCtlVRequest& ioctlv);
V0CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V0BulkMessage final : BulkMessage
{
explicit V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length = false);
V0BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv, bool long_length = false);
};
struct V0IntrMessage final : IntrMessage
{
explicit V0IntrMessage(const IOCtlVRequest& ioctlv);
V0IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V0IsoMessage final : IsoMessage
{
explicit V0IsoMessage(const IOCtlVRequest& ioctlv);
V0IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
} // namespace USB
} // namespace HLE

View File

@ -49,7 +49,7 @@ struct HIDRequest
};
#pragma pack(pop)
V4CtrlMessage::V4CtrlMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1)
V4CtrlMessage::V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl) : CtrlMessage(ios, ioctl, -1)
{
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
@ -64,7 +64,8 @@ V4CtrlMessage::V4CtrlMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1)
// Since this is just a standard control request, but with additional requirements
// (US for the language and replacing non-ASCII characters with '?'),
// we can simply submit it as a usual control request.
V4GetUSStringMessage::V4GetUSStringMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1)
V4GetUSStringMessage::V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl)
: CtrlMessage(ios, ioctl, -1)
{
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
@ -76,16 +77,17 @@ V4GetUSStringMessage::V4GetUSStringMessage(const IOCtlRequest& ioctl) : CtrlMess
data_address = Common::swap32(hid_request.data_addr);
}
void V4GetUSStringMessage::OnTransferComplete() const
void V4GetUSStringMessage::OnTransferComplete(s32 return_value) const
{
const std::locale& c_locale = std::locale::classic();
std::string message = Memory::GetString(data_address);
std::replace_if(message.begin(), message.end(),
[&c_locale](char c) { return !std::isprint(c, c_locale); }, '?');
Memory::CopyToEmu(data_address, message.c_str(), message.size());
TransferCommand::OnTransferComplete(return_value);
}
V4IntrMessage::V4IntrMessage(const IOCtlRequest& ioctl) : IntrMessage(ioctl, -1)
V4IntrMessage::V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl) : IntrMessage(ios, ioctl, -1)
{
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));

View File

@ -32,18 +32,18 @@ enum V4Requests
struct V4CtrlMessage final : CtrlMessage
{
explicit V4CtrlMessage(const IOCtlRequest& ioctl);
V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl);
};
struct V4GetUSStringMessage final : CtrlMessage
{
explicit V4GetUSStringMessage(const IOCtlRequest& ioctl);
void OnTransferComplete() const override;
V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl);
void OnTransferComplete(s32 return_value) const override;
};
struct V4IntrMessage final : IntrMessage
{
explicit V4IntrMessage(const IOCtlRequest& ioctl);
V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl);
};
} // namespace USB
} // namespace HLE

View File

@ -16,8 +16,8 @@ namespace HLE
{
namespace USB
{
V5CtrlMessage::V5CtrlMessage(const IOCtlVRequest& ioctlv)
: CtrlMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 16))
V5CtrlMessage::V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: CtrlMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 16))
{
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address + 8);
request = Memory::Read_U8(ioctlv.in_vectors[0].address + 9);
@ -26,22 +26,22 @@ V5CtrlMessage::V5CtrlMessage(const IOCtlVRequest& ioctlv)
length = Memory::Read_U16(ioctlv.in_vectors[0].address + 14);
}
V5BulkMessage::V5BulkMessage(const IOCtlVRequest& ioctlv)
: BulkMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
V5BulkMessage::V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: BulkMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
{
length = Memory::Read_U16(ioctlv.in_vectors[0].address + 12);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 18);
}
V5IntrMessage::V5IntrMessage(const IOCtlVRequest& ioctlv)
: IntrMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
V5IntrMessage::V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IntrMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
{
length = Memory::Read_U16(ioctlv.in_vectors[0].address + 12);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 14);
}
V5IsoMessage::V5IsoMessage(const IOCtlVRequest& ioctlv)
: IsoMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
V5IsoMessage::V5IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IsoMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
{
num_packets = Memory::Read_U8(ioctlv.in_vectors[0].address + 16);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 17);

View File

@ -36,22 +36,22 @@ enum V5Requests
struct V5CtrlMessage final : CtrlMessage
{
explicit V5CtrlMessage(const IOCtlVRequest& ioctlv);
V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V5BulkMessage final : BulkMessage
{
explicit V5BulkMessage(const IOCtlVRequest& ioctlv);
V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V5IntrMessage final : IntrMessage
{
explicit V5IntrMessage(const IOCtlVRequest& ioctlv);
V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V5IsoMessage final : IsoMessage
{
explicit V5IsoMessage(const IOCtlVRequest& cmd_buffer);
V5IsoMessage(Kernel& ios, const IOCtlVRequest& cmd_buffer);
};
} // namespace USB
} // namespace HLE

View File

@ -23,8 +23,7 @@ namespace HLE
{
namespace Device
{
USB_HIDv4::USB_HIDv4(u32 device_id, const std::string& device_name)
: USBHost(device_id, device_name)
USB_HIDv4::USB_HIDv4(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name)
{
}
@ -102,7 +101,7 @@ IPCCommandResult USB_HIDv4::Shutdown(const IOCtlRequest& request)
if (m_devicechange_hook_request != 0)
{
Memory::Write_U32(0xffffffff, m_devicechange_hook_request->buffer_out);
EnqueueReply(*m_devicechange_hook_request, -1);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, -1);
m_devicechange_hook_request.reset();
}
return GetDefaultReply(IPC_SUCCESS);
@ -113,12 +112,12 @@ s32 USB_HIDv4::SubmitTransfer(USB::Device& device, const IOCtlRequest& request)
switch (request.request)
{
case USB::IOCTL_USBV4_CTRLMSG:
return device.SubmitTransfer(std::make_unique<USB::V4CtrlMessage>(request));
return device.SubmitTransfer(std::make_unique<USB::V4CtrlMessage>(m_ios, request));
case USB::IOCTL_USBV4_GET_US_STRING:
return device.SubmitTransfer(std::make_unique<USB::V4GetUSStringMessage>(request));
return device.SubmitTransfer(std::make_unique<USB::V4GetUSStringMessage>(m_ios, request));
case USB::IOCTL_USBV4_INTRMSG_IN:
case USB::IOCTL_USBV4_INTRMSG_OUT:
return device.SubmitTransfer(std::make_unique<USB::V4IntrMessage>(request));
return device.SubmitTransfer(std::make_unique<USB::V4IntrMessage>(m_ios, request));
default:
return IPC_EINVAL;
}
@ -204,7 +203,7 @@ void USB_HIDv4::TriggerDeviceChangeReply()
Memory::Write_U32(0xffffffff, dest + offset);
}
EnqueueReply(*m_devicechange_hook_request, IPC_SUCCESS, 0, CoreTiming::FromThread::ANY);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS, 0, CoreTiming::FromThread::ANY);
m_devicechange_hook_request.reset();
}

View File

@ -11,7 +11,7 @@
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Host.h"
class PointerWrap;
@ -25,7 +25,7 @@ namespace Device
class USB_HIDv4 final : public USBHost
{
public:
USB_HIDv4(u32 device_id, const std::string& device_name);
USB_HIDv4(Kernel& ios, const std::string& device_name);
~USB_HIDv4() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -39,7 +39,7 @@ USB_KBD::SMessageData::SMessageData(u32 type, u8 modifiers, u8* pressed_keys)
// TODO: support in netplay/movies.
USB_KBD::USB_KBD(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -9,7 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -20,7 +20,7 @@ namespace Device
class USB_KBD : public Device
{
public:
USB_KBD(u32 device_id, const std::string& device_name);
USB_KBD(Kernel& ios, const std::string& device_name);
ReturnCode Open(const OpenRequest& request) override;
IPCCommandResult Write(const ReadWriteRequest& request) override;

View File

@ -22,7 +22,7 @@ namespace HLE
{
namespace Device
{
USB_VEN::USB_VEN(u32 device_id, const std::string& device_name) : USBHost(device_id, device_name)
USB_VEN::USB_VEN(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name)
{
}
@ -33,7 +33,7 @@ USB_VEN::~USB_VEN()
ReturnCode USB_VEN::Open(const OpenRequest& request)
{
const u32 ios_major_version = GetVersion();
const u32 ios_major_version = m_ios.GetVersion();
if (ios_major_version != 57 && ios_major_version != 58 && ios_major_version != 59)
return IPC_ENOENT;
return USBHost::Open(request);
@ -197,7 +197,7 @@ IPCCommandResult USB_VEN::Shutdown(const IOCtlRequest& request)
std::lock_guard<std::mutex> lk{m_devicechange_hook_address_mutex};
if (m_devicechange_hook_request)
{
EnqueueReply(*m_devicechange_hook_request, IPC_SUCCESS);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS);
m_devicechange_hook_request.reset();
}
return GetDefaultReply(IPC_SUCCESS);
@ -220,13 +220,13 @@ s32 USB_VEN::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
switch (ioctlv.request)
{
case USB::IOCTLV_USBV5_CTRLMSG:
return device.SubmitTransfer(std::make_unique<USB::V5CtrlMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5CtrlMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV5_INTRMSG:
return device.SubmitTransfer(std::make_unique<USB::V5IntrMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5IntrMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV5_BULKMSG:
return device.SubmitTransfer(std::make_unique<USB::V5BulkMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5BulkMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV5_ISOMSG:
return device.SubmitTransfer(std::make_unique<USB::V5IsoMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5IsoMessage>(m_ios, ioctlv));
default:
return IPC_EINVAL;
}
@ -326,7 +326,7 @@ void USB_VEN::TriggerDeviceChangeReply()
&entry, sizeof(entry));
}
EnqueueReply(*m_devicechange_hook_request, num_devices, 0, CoreTiming::FromThread::ANY);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, num_devices, 0, CoreTiming::FromThread::ANY);
m_devicechange_hook_request.reset();
INFO_LOG(IOS_USB, "%d device(s), including interfaces", num_devices);
}

View File

@ -14,7 +14,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Host.h"
class PointerWrap;
@ -28,7 +28,7 @@ namespace Device
class USB_VEN final : public USBHost
{
public:
USB_VEN(u32 device_id, const std::string& device_name);
USB_VEN(Kernel& ios, const std::string& device_name);
~USB_VEN() override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -80,7 +80,7 @@ void ARCUnpacker::Extract(const WriteCallback& callback)
namespace Device
{
WFSI::WFSI(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
WFSI::WFSI(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -13,7 +13,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -39,7 +39,7 @@ namespace Device
class WFSI : public Device
{
public:
WFSI(u32 device_id, const std::string& device_name);
WFSI(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -27,7 +27,7 @@ std::string NativePath(const std::string& wfs_path)
namespace Device
{
WFSSRV::WFSSRV(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
WFSSRV::WFSSRV(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
m_device_name = "msc01";
}

View File

@ -10,7 +10,7 @@
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "DiscIO/Volume.h"
namespace IOS
@ -27,7 +27,7 @@ namespace Device
class WFSSRV : public Device
{
public:
WFSSRV(u32 device_id, const std::string& device_name);
WFSSRV(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -533,8 +533,10 @@ void ChangeWiiPads(bool instantly)
if (instantly && (s_controllers >> 4) == controllers)
return;
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
const auto ios = IOS::HLE::GetIOS();
const auto bt = ios ? std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305")) :
nullptr;
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 82; // Last changed in PR 5333
static const u32 STATE_VERSION = 83; // Last changed in PR 5340
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,

View File

@ -23,7 +23,7 @@
#include "Core/Core.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
@ -139,19 +139,18 @@ bool Host_RendererIsFullscreen()
void Host_ConnectWiimote(int wm_idx, bool connect)
{
if (Core::IsRunning() && SConfig::GetInstance().bWii &&
!SConfig::GetInstance().m_bt_passthrough_enabled)
{
Core::QueueHostJob([=] {
bool was_unpaused = Core::PauseAndLock(true);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused);
});
}
Core::QueueHostJob([=] {
const auto ios = IOS::HLE::GetIOS();
if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled)
return;
bool was_unpaused = Core::PauseAndLock(true);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused);
});
}
void Host_SetWiiMoteConnectionState(int _State)
@ -241,7 +240,8 @@ class PlatformX11 : public Platform
{
if (s_shutdown_requested.TestAndClear())
{
const auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
const auto ios = IOS::HLE::GetIOS();
const auto stm = ios ? ios->GetDeviceByName("/dev/stm/eventhook") : nullptr;
if (!s_tried_graceful_shutdown.IsSet() && stm &&
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->HasHookInstalled())
{

View File

@ -13,7 +13,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "DolphinWX/Config/AddUSBDeviceDiag.h"
#include "DolphinWX/Config/WiiConfigPane.h"
#include "DolphinWX/DolphinSlider.h"
@ -279,7 +279,9 @@ void WiiConfigPane::OnPAL60CheckBoxChanged(wxCommandEvent& event)
void WiiConfigPane::OnSDCardCheckBoxChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiiSDCard = m_sd_card_checkbox->IsChecked();
IOS::HLE::SDIO_EventNotify();
const auto ios = IOS::HLE::GetIOS();
if (ios)
ios->SDIO_EventNotify();
}
void WiiConfigPane::OnConnectKeyboardCheckBoxChanged(wxCommandEvent& event)

View File

@ -27,7 +27,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/HotkeyManager.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTReal.h"
#include "Core/NetPlayProto.h"
#include "DolphinWX/Config/GCAdapterConfigDiag.h"
@ -543,13 +543,14 @@ void ControllerConfigDiag::OnBluetoothModeChanged(wxCommandEvent& event)
void ControllerConfigDiag::OnPassthroughScanButton(wxCommandEvent& event)
{
if (!Core::IsRunning())
const auto ios = IOS::HLE::GetIOS();
if (!ios)
{
wxMessageBox(_("A sync can only be triggered when a Wii game is running."),
_("Sync Wii Remotes"), wxICON_WARNING);
return;
}
auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305");
auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305");
if (device != nullptr)
std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device)
->TriggerSyncButtonPressedEvent();
@ -557,13 +558,14 @@ void ControllerConfigDiag::OnPassthroughScanButton(wxCommandEvent& event)
void ControllerConfigDiag::OnPassthroughResetButton(wxCommandEvent& event)
{
if (!Core::IsRunning())
const auto ios = IOS::HLE::GetIOS();
if (!ios)
{
wxMessageBox(_("Saved Wii Remote pairings can only be reset when a Wii game is running."),
_("Reset Wii Remote pairings"), wxICON_WARNING);
return;
}
auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305");
auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305");
if (device != nullptr)
std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device)->TriggerSyncButtonHeldEvent();
}

View File

@ -50,7 +50,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "Core/HotkeyManager.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/Movie.h"
#include "Core/State.h"
@ -1278,7 +1278,8 @@ void CFrame::ParseHotkeys()
if (SConfig::GetInstance().m_bt_passthrough_enabled)
{
auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305");
const auto ios = IOS::HLE::GetIOS();
auto device = ios ? ios->GetDeviceByName("/dev/usb/oh1/57e/305") : nullptr;
if (device != nullptr)
std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device)->UpdateSyncButtonState(
IsHotkey(HK_TRIGGER_SYNC_BUTTON, true));

View File

@ -42,7 +42,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/HotkeyManager.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
@ -880,7 +880,11 @@ void CFrame::DoStop()
bool CFrame::TriggerSTMPowerEvent()
{
const auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return false;
const auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (!stm || !std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->HasHookInstalled())
return false;
@ -1310,8 +1314,12 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
!SConfig::GetInstance().m_bt_passthrough_enabled)
{
bool was_unpaused = Core::PauseAndLock(true);
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected";
@ -1323,11 +1331,12 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
void CFrame::OnConnectWiimote(wxCommandEvent& event)
{
if (SConfig::GetInstance().m_bt_passthrough_enabled)
const auto ios = IOS::HLE::GetIOS();
if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled)
return;
bool was_unpaused = Core::PauseAndLock(true);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
const bool is_connected =
bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected();
ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected);
@ -1486,8 +1495,10 @@ void CFrame::UpdateGUI()
// Tools
GetMenuBar()->FindItem(IDM_CHEATS)->Enable(SConfig::GetInstance().bEnableCheats);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
const auto ios = IOS::HLE::GetIOS();
const auto bt = ios ? std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305")) :
nullptr;
bool ShouldEnableWiimotes = Running && bt && !SConfig::GetInstance().m_bt_passthrough_enabled;
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(ShouldEnableWiimotes);