summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/function_wrappers.h15
-rw-r--r--src/core/hle/kernel/errors.h5
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp24
-rw-r--r--src/core/hle/kernel/hle_ipc.h7
-rw-r--r--src/core/hle/kernel/memory.cpp6
-rw-r--r--src/core/hle/kernel/process.cpp2
-rw-r--r--src/core/hle/kernel/server_port.cpp12
-rw-r--r--src/core/hle/kernel/server_port.h11
-rw-r--r--src/core/hle/kernel/server_session.cpp2
-rw-r--r--src/core/hle/kernel/thread.cpp4
-rw-r--r--src/core/hle/kernel/timer.cpp2
-rw-r--r--src/core/hle/result.h7
-rw-r--r--src/core/hle/service/apt/apt.cpp12
-rw-r--r--src/core/hle/service/cam/cam.cpp6
-rw-r--r--src/core/hle/service/cecd/cecd.cpp8
-rw-r--r--src/core/hle/service/cfg/cfg.cpp4
-rw-r--r--src/core/hle/service/csnd_snd.cpp4
-rw-r--r--src/core/hle/service/dsp_dsp.cpp2
-rw-r--r--src/core/hle/service/fs/archive.cpp4
-rw-r--r--src/core/hle/service/fs/fs_user.cpp6
-rw-r--r--src/core/hle/service/gsp_gpu.cpp4
-rw-r--r--src/core/hle/service/hid/hid.cpp12
-rw-r--r--src/core/hle/service/ir/ir_rst.cpp4
-rw-r--r--src/core/hle/service/ir/ir_user.cpp6
-rw-r--r--src/core/hle/service/mic_u.cpp2
-rw-r--r--src/core/hle/service/nfc/nfc.cpp4
-rw-r--r--src/core/hle/service/nwm/nwm_uds.cpp40
-rw-r--r--src/core/hle/service/ptm/ptm.cpp2
-rw-r--r--src/core/hle/service/service.cpp5
-rw-r--r--src/core/hle/service/sm/srv.cpp4
-rw-r--r--src/core/hle/service/y2r_u.cpp2
-rw-r--r--src/core/hle/svc.cpp45
32 files changed, 195 insertions, 78 deletions
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 18b6e7017..410bb87ea 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -226,9 +226,18 @@ void Wrap() {
u32 retval = func(&param_1, &param_2,
reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3))
.raw;
- // The first out parameter is moved into R2 and the second is moved into R1.
- Core::CPU().SetReg(1, param_2);
- Core::CPU().SetReg(2, param_1);
+ Core::CPU().SetReg(1, param_1);
+ Core::CPU().SetReg(2, param_2);
+ FuncReturn(retval);
+}
+
+template <ResultCode func(Kernel::Handle*, Kernel::Handle*)>
+void Wrap() {
+ Kernel::Handle param_1 = 0;
+ Kernel::Handle param_2 = 0;
+ u32 retval = func(&param_1, &param_2).raw;
+ Core::CPU().SetReg(1, param_1);
+ Core::CPU().SetReg(2, param_2);
FuncReturn(retval);
}
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index b3b60e7df..64aa61460 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -13,6 +13,7 @@ enum {
OutOfHandles = 19,
SessionClosedByRemote = 26,
PortNameTooLong = 30,
+ NoPendingSessions = 35,
WrongPermission = 46,
InvalidBufferDescriptor = 48,
MaxConnectionsReached = 52,
@@ -94,5 +95,9 @@ constexpr ResultCode ERR_OUT_OF_RANGE_KERNEL(ErrorDescription::OutOfRange, Error
ErrorLevel::Permanent); // 0xD8E007FD
constexpr ResultCode RESULT_TIMEOUT(ErrorDescription::Timeout, ErrorModule::OS,
ErrorSummary::StatusChanged, ErrorLevel::Info);
+/// Returned when Accept() is called on a port with no sessions to be accepted.
+constexpr ResultCode ERR_NO_PENDING_SESSIONS(ErrCodes::NoPendingSessions, ErrorModule::OS,
+ ErrorSummary::WouldBlock,
+ ErrorLevel::Permanent); // 0xD8401823
} // namespace Kernel
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 6cf1886cf..5ebe2eca4 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -23,6 +23,11 @@ void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_s
boost::range::remove_erase(connected_sessions, server_session);
}
+HLERequestContext::HLERequestContext(SharedPtr<ServerSession> session)
+ : session(std::move(session)) {
+ cmd_buf[0] = 0;
+}
+
HLERequestContext::~HLERequestContext() = default;
SharedPtr<Object> HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const {
@@ -62,10 +67,13 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
ASSERT(i + num_handles <= command_size); // TODO(yuriks): Return error
for (u32 j = 0; j < num_handles; ++j) {
Handle handle = src_cmdbuf[i];
- SharedPtr<Object> object = src_table.GetGeneric(handle);
- ASSERT(object != nullptr); // TODO(yuriks): Return error
- if (descriptor == IPC::DescriptorType::MoveHandle) {
- src_table.Close(handle);
+ SharedPtr<Object> object = nullptr;
+ if (handle != 0) {
+ object = src_table.GetGeneric(handle);
+ ASSERT(object != nullptr); // TODO(yuriks): Return error
+ if (descriptor == IPC::DescriptorType::MoveHandle) {
+ src_table.Close(handle);
+ }
}
cmd_buf[i++] = AddOutgoingHandle(std::move(object));
@@ -107,9 +115,11 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P
ASSERT(i + num_handles <= command_size);
for (u32 j = 0; j < num_handles; ++j) {
SharedPtr<Object> object = GetIncomingHandle(cmd_buf[i]);
-
- // TODO(yuriks): Figure out the proper error handling for if this fails
- Handle handle = dst_table.Create(object).Unwrap();
+ Handle handle = 0;
+ if (object != nullptr) {
+ // TODO(yuriks): Figure out the proper error handling for if this fails
+ handle = dst_table.Create(object).Unwrap();
+ }
dst_cmdbuf[i++] = handle;
}
break;
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index cbb109d8f..35795fc1d 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -84,6 +84,7 @@ protected:
*/
class HLERequestContext {
public:
+ HLERequestContext(SharedPtr<ServerSession> session);
~HLERequestContext();
/// Returns a pointer to the IPC command buffer for this request.
@@ -118,14 +119,14 @@ public:
*/
void ClearIncomingObjects();
-private:
- friend class Service::ServiceFrameworkBase;
-
+ /// Populates this context with data from the requesting process/thread.
ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process,
HandleTable& src_table);
+ /// Writes data from this context back to the requesting process/thread.
ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process,
HandleTable& dst_table) const;
+private:
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
SharedPtr<ServerSession> session;
// TODO(yuriks): Check common usage of this and optimize size accordingly
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 804f23b1c..496d07cb5 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -166,7 +166,7 @@ void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mappin
auto vma = address_space
.MapBackingMemory(mapping.address, target_pointer + offset_into_region,
mapping.size, memory_state)
- .MoveFrom();
+ .Unwrap();
address_space.Reprotect(vma,
mapping.read_only ? VMAPermission::Read : VMAPermission::ReadWrite);
}
@@ -176,14 +176,14 @@ void MapSharedPages(VMManager& address_space) {
.MapBackingMemory(Memory::CONFIG_MEMORY_VADDR,
reinterpret_cast<u8*>(&ConfigMem::config_mem),
Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared)
- .MoveFrom();
+ .Unwrap();
address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
auto shared_page_vma = address_space
.MapBackingMemory(Memory::SHARED_PAGE_VADDR,
reinterpret_cast<u8*>(&SharedPage::shared_page),
Memory::SHARED_PAGE_SIZE, MemoryState::Shared)
- .MoveFrom();
+ .Unwrap();
address_space.Reprotect(shared_page_vma, VMAPermission::Read);
}
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 1c31ec950..522ad2333 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -151,6 +151,8 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
}
VAddr Process::GetLinearHeapAreaAddress() const {
+ // Starting from system version 8.0.0 a new linear heap layout is supported to allow usage of
+ // the extra RAM in the n3DS.
return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR;
}
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 4d20c39a1..49a9cdfa3 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -5,8 +5,10 @@
#include <tuple>
#include "common/assert.h"
#include "core/hle/kernel/client_port.h"
+#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/server_port.h"
+#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/thread.h"
namespace Kernel {
@@ -14,6 +16,16 @@ namespace Kernel {
ServerPort::ServerPort() {}
ServerPort::~ServerPort() {}
+ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
+ if (pending_sessions.empty()) {
+ return ERR_NO_PENDING_SESSIONS;
+ }
+
+ auto session = std::move(pending_sessions.back());
+ pending_sessions.pop_back();
+ return MakeResult(std::move(session));
+}
+
bool ServerPort::ShouldWait(Thread* thread) const {
// If there are no pending sessions, we wait until a new one is added.
return pending_sessions.size() == 0;
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index f1419cd46..6fe7c7f2f 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -14,6 +14,7 @@
namespace Kernel {
class ClientPort;
+class ServerSession;
class SessionRequestHandler;
class ServerPort final : public WaitObject {
@@ -41,6 +42,12 @@ public:
}
/**
+ * Accepts a pending incoming connection on this port. If there are no pending sessions, will
+ * return ERR_NO_PENDING_SESSIONS.
+ */
+ ResultVal<SharedPtr<ServerSession>> Accept();
+
+ /**
* Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
* will inherit a reference to this handler.
*/
@@ -50,8 +57,8 @@ public:
std::string name; ///< Name of port (optional)
- std::vector<SharedPtr<WaitObject>>
- pending_sessions; ///< ServerSessions waiting to be accepted by the port
+ /// ServerSessions waiting to be accepted by the port
+ std::vector<SharedPtr<ServerSession>> pending_sessions;
/// This session's HLE request handler template (optional)
/// ServerSessions created from this port inherit a reference to this handler.
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 2dc709bc9..d197137c3 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -71,7 +71,7 @@ ResultCode ServerSession::HandleSyncRequest() {
ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name,
SharedPtr<ClientPort> port) {
- auto server_session = ServerSession::Create(name + "_Server").MoveFrom();
+ auto server_session = ServerSession::Create(name + "_Server").Unwrap();
SharedPtr<ClientSession> client_session(new ClientSession);
client_session->name = name + "_Client";
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 75ce626f8..f5f2eb2f7 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -389,7 +389,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->wait_objects.clear();
thread->wait_address = 0;
thread->name = std::move(name);
- thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom();
+ thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
thread->owner_process = g_current_process;
// Find the next available TLS index, and mark it as used
@@ -484,7 +484,7 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
Memory::HEAP_VADDR_END);
- SharedPtr<Thread> thread = thread_res.MoveFrom();
+ SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
thread->context.fpscr =
FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 6f2cf3b02..d7ec93672 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -30,7 +30,7 @@ SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
timer->name = std::move(name);
timer->initial_delay = 0;
timer->interval_delay = 0;
- timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom();
+ timer->callback_handle = timer_callback_handle_table.Create(timer).Unwrap();
return timer;
}
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 5f2cdbb96..47b6e2b23 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -388,13 +388,14 @@ public:
}
/// Asserts that the result succeeded and returns a reference to it.
- T& Unwrap() {
+ T& Unwrap() & {
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
return **this;
}
- T&& MoveFrom() {
- return std::move(Unwrap());
+ T&& Unwrap() && {
+ ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
+ return std::move(**this);
}
private:
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 4c587e3c8..25e7b777d 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -55,8 +55,8 @@ void Initialize(Service::Interface* self) {
u32 flags = rp.Pop<u32>();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(notification_event).MoveFrom(),
- Kernel::g_handle_table.Create(parameter_event).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(notification_event).Unwrap(),
+ Kernel::g_handle_table.Create(parameter_event).Unwrap());
// TODO(bunnei): Check if these events are cleared every time Initialize is called.
notification_event->Clear();
@@ -93,7 +93,7 @@ void GetSharedFont(Service::Interface* self) {
// allocated, the real APT service calculates this address by scanning the entire address space
// (using svcQueryMemory) and searches for an allocation of the same size as the Shared Font.
rb.Push(target_address);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(shared_font_mem).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(shared_font_mem).Unwrap());
}
void NotifyToWait(Service::Interface* self) {
@@ -115,7 +115,7 @@ void GetLockHandle(Service::Interface* self) {
rb.Push(RESULT_SUCCESS); // No error
rb.Push(applet_attributes); // Applet Attributes, this value is passed to Enable.
rb.Push<u32>(0); // Least significant bit = power button state
- Kernel::Handle handle_copy = Kernel::g_handle_table.Create(lock).MoveFrom();
+ Kernel::Handle handle_copy = Kernel::g_handle_table.Create(lock).Unwrap();
rb.PushCopyHandles(handle_copy);
LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", handle_copy,
@@ -231,7 +231,7 @@ void ReceiveParameter(Service::Interface* self) {
rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size
rb.PushMoveHandles((next_parameter.object != nullptr)
- ? Kernel::g_handle_table.Create(next_parameter.object).MoveFrom()
+ ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap()
: 0);
rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0);
@@ -261,7 +261,7 @@ void GlanceParameter(Service::Interface* self) {
rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size
rb.PushCopyHandles((next_parameter.object != nullptr)
- ? Kernel::g_handle_table.Create(next_parameter.object).MoveFrom()
+ ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap()
: 0);
rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0);
diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp
index 7394c844f..c9f9e9d95 100644
--- a/src/core/hle/service/cam/cam.cpp
+++ b/src/core/hle/service/cam/cam.cpp
@@ -347,7 +347,7 @@ void GetVsyncInterruptEvent(Service::Interface* self) {
int port = *port_select.begin();
rb.Push(RESULT_SUCCESS);
rb.PushCopyHandles(
- Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).MoveFrom());
+ Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).Unwrap());
} else {
LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE);
@@ -366,7 +366,7 @@ void GetBufferErrorInterruptEvent(Service::Interface* self) {
int port = *port_select.begin();
rb.Push(RESULT_SUCCESS);
rb.PushCopyHandles(
- Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).MoveFrom());
+ Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).Unwrap());
} else {
LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE);
@@ -400,7 +400,7 @@ void SetReceiving(Service::Interface* self) {
}
rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(port.completion_event).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(port.completion_event).Unwrap());
} else {
LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val);
rb.Push(ERROR_INVALID_ENUM_VALUE);
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp
index bd9814244..421006a9e 100644
--- a/src/core/hle/service/cecd/cecd.cpp
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -31,8 +31,8 @@ void GetCecStateAbbreviated(Service::Interface* self) {
void GetCecInfoEventHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).Unwrap(); // Event handle
LOG_WARNING(Service_CECD, "(STUBBED) called");
}
@@ -40,8 +40,8 @@ void GetCecInfoEventHandle(Service::Interface* self) {
void GetChangeStateEventHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).Unwrap(); // Event handle
LOG_WARNING(Service_CECD, "(STUBBED) called");
}
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index 5a7878b31..6624f1711 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -406,7 +406,7 @@ ResultCode UpdateConfigNANDSavegame() {
auto config_result = Service::FS::OpenFileFromArchive(cfg_system_save_data_archive, path, mode);
ASSERT_MSG(config_result.Succeeded(), "could not open file");
- auto config = config_result.MoveFrom();
+ auto config = std::move(config_result).Unwrap();
config->backend->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data());
return RESULT_SUCCESS;
@@ -560,7 +560,7 @@ ResultCode LoadConfigNANDSaveFile() {
// Read the file if it already exists
if (config_result.Succeeded()) {
- auto config = config_result.MoveFrom();
+ auto config = std::move(config_result).Unwrap();
config->backend->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data());
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 1455f20ca..9471ec1ef 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -51,8 +51,8 @@ static void Initialize(Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = IPC::CopyHandleDesc(2);
- cmd_buff[3] = Kernel::g_handle_table.Create(mutex).MoveFrom();
- cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).MoveFrom();
+ cmd_buff[3] = Kernel::g_handle_table.Create(mutex).Unwrap();
+ cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).Unwrap();
LOG_WARNING(Service_CSND, "(STUBBED) called");
}
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index 363066d14..7d746054f 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -168,7 +168,7 @@ static void GetSemaphoreEventHandle(Service::Interface* self) {
cmd_buff[0] = IPC::MakeHeader(0x16, 1, 2);
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
// cmd_buff[2] not set
- cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle
+ cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).Unwrap(); // Event handle
LOG_WARNING(Service_DSP, "(STUBBED) called");
}
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 3605ef175..033fbc9aa 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -311,7 +311,7 @@ ResultVal<std::shared_ptr<File>> OpenFileFromArchive(ArchiveHandle archive_handl
if (backend.Failed())
return backend.Code();
- auto file = std::shared_ptr<File>(new File(backend.MoveFrom(), path));
+ auto file = std::shared_ptr<File>(new File(std::move(backend).Unwrap(), path));
return MakeResult<std::shared_ptr<File>>(std::move(file));
}
@@ -401,7 +401,7 @@ ResultVal<std::shared_ptr<Directory>> OpenDirectoryFromArchive(ArchiveHandle arc
if (backend.Failed())
return backend.Code();
- auto directory = std::shared_ptr<Directory>(new Directory(backend.MoveFrom(), path));
+ auto directory = std::shared_ptr<Directory>(new Directory(std::move(backend).Unwrap(), path));
return MakeResult<std::shared_ptr<Directory>>(std::move(directory));
}
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 34e1783ec..b9eab7838 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -87,7 +87,7 @@ static void OpenFile(Service::Interface* self) {
file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
rb.PushMoveHandles(
- Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom());
+ Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).Unwrap());
} else {
rb.PushMoveHandles(0);
LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
@@ -153,7 +153,7 @@ static void OpenFileDirectly(Service::Interface* self) {
file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
cmd_buff[3] =
- Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom();
+ Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).Unwrap();
} else {
cmd_buff[3] = 0;
LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u",
@@ -420,7 +420,7 @@ static void OpenDirectory(Service::Interface* self) {
directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
cmd_buff[3] =
- Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom();
+ Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).Unwrap();
} else {
LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s",
dirname_type, dirname_size, dir_path.DebugStr().c_str());
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 6ff0f4812..bc964ec60 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -389,8 +389,8 @@ static void RegisterInterruptRelayQueue(Interface* self) {
} else {
cmd_buff[1] = RESULT_SUCCESS.raw;
}
- cmd_buff[2] = g_thread_id++; // Thread ID
- cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory
+ cmd_buff[2] = g_thread_id++; // Thread ID
+ cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).Unwrap(); // GSP shared memory
g_interrupt_event->Signal(); // TODO(bunnei): Is this correct?
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 5255f6dc8..2014b8461 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -253,12 +253,12 @@ void GetIPCHandles(Service::Interface* self) {
cmd_buff[1] = 0; // No error
cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
// TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
- cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom();
- cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).MoveFrom();
- cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_2).MoveFrom();
- cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::event_accelerometer).MoveFrom();
- cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::event_gyroscope).MoveFrom();
- cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).MoveFrom();
+ cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).Unwrap();
+ cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).Unwrap();
+ cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_2).Unwrap();
+ cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::event_accelerometer).Unwrap();
+ cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::event_gyroscope).Unwrap();
+ cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).Unwrap();
}
void EnableAccelerometer(Service::Interface* self) {
diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp
index 0de698003..837413f93 100644
--- a/src/core/hle/service/ir/ir_rst.cpp
+++ b/src/core/hle/service/ir/ir_rst.cpp
@@ -145,8 +145,8 @@ static void GetHandles(Interface* self) {
IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 0, 0);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
rb.Push(RESULT_SUCCESS);
- rb.PushMoveHandles(Kernel::g_handle_table.Create(Service::IR::shared_memory).MoveFrom(),
- Kernel::g_handle_table.Create(Service::IR::update_event).MoveFrom());
+ rb.PushMoveHandles(Kernel::g_handle_table.Create(Service::IR::shared_memory).Unwrap(),
+ Kernel::g_handle_table.Create(Service::IR::update_event).Unwrap());
}
/**
diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp
index fdecdce64..fbdf7a465 100644
--- a/src/core/hle/service/ir/ir_user.cpp
+++ b/src/core/hle/service/ir/ir_user.cpp
@@ -337,7 +337,7 @@ void GetReceiveEvent(Interface* self) {
IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0A, 1, 2);
rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::receive_event).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::receive_event).Unwrap());
LOG_INFO(Service_IR, "called");
}
@@ -354,7 +354,7 @@ void GetSendEvent(Interface* self) {
IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0B, 1, 2);
rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::send_event).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::send_event).Unwrap());
LOG_INFO(Service_IR, "called");
}
@@ -394,7 +394,7 @@ static void GetConnectionStatusEvent(Interface* self) {
IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0C, 1, 2);
rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::conn_status_event).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::conn_status_event).Unwrap());
LOG_INFO(Service_IR, "called");
}
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 35212b59b..23e1ff094 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -160,7 +160,7 @@ static void IsSampling(Interface* self) {
static void GetBufferFullEvent(Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- cmd_buff[3] = Kernel::g_handle_table.Create(buffer_full_event).MoveFrom();
+ cmd_buff[3] = Kernel::g_handle_table.Create(buffer_full_event).Unwrap();
LOG_WARNING(Service_MIC, "(STUBBED) called");
}
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index b44a9f668..cb09ed0b7 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -95,7 +95,7 @@ void GetTagInRangeEvent(Interface* self) {
cmd_buff[0] = IPC::MakeHeader(0xB, 1, 2);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = IPC::CopyHandleDesc();
- cmd_buff[3] = Kernel::g_handle_table.Create(tag_in_range_event).MoveFrom();
+ cmd_buff[3] = Kernel::g_handle_table.Create(tag_in_range_event).Unwrap();
LOG_WARNING(Service_NFC, "(STUBBED) called");
}
@@ -105,7 +105,7 @@ void GetTagOutOfRangeEvent(Interface* self) {
cmd_buff[0] = IPC::MakeHeader(0xC, 1, 2);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = IPC::CopyHandleDesc();
- cmd_buff[3] = Kernel::g_handle_table.Create(tag_out_of_range_event).MoveFrom();
+ cmd_buff[3] = Kernel::g_handle_table.Create(tag_out_of_range_event).Unwrap();
LOG_WARNING(Service_NFC, "(STUBBED) called");
}
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp
index 35fa1cd77..6dbdff044 100644
--- a/src/core/hle/service/nwm/nwm_uds.cpp
+++ b/src/core/hle/service/nwm/nwm_uds.cpp
@@ -191,7 +191,7 @@ static void InitializeWithVersion(Interface* self) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).Unwrap());
LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X",
sharedmem_size, version, sharedmem_handle);
@@ -266,7 +266,7 @@ static void Bind(Interface* self) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(event).MoveFrom());
+ rb.PushCopyHandles(Kernel::g_handle_table.Create(event).Unwrap());
}
/**
@@ -618,6 +618,42 @@ static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
beacon_broadcast_event, 0);
}
+/*
+ * Returns an available index in the nodes array for the
+ * currently-hosted UDS network.
+ */
+static u32 GetNextAvailableNodeId() {
+ ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
+ "Can not accept clients if we're not hosting a network");
+
+ for (unsigned index = 0; index < connection_status.max_nodes; ++index) {
+ if ((connection_status.node_bitmask & (1 << index)) == 0)
+ return index;
+ }
+
+ // Any connection attempts to an already full network should have been refused.
+ ASSERT_MSG(false, "No available connection slots in the network");
+}
+
+/*
+ * Called when a client connects to an UDS network we're hosting,
+ * updates the connection status and signals the update event.
+ * @param network_node_id Network Node Id of the connecting client.
+ */
+void OnClientConnected(u16 network_node_id) {
+ ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
+ "Can not accept clients if we're not hosting a network");
+ ASSERT_MSG(connection_status.total_nodes < connection_status.max_nodes,
+ "Can not accept connections on a full network");
+
+ u32 node_id = GetNextAvailableNodeId();
+ connection_status.node_bitmask |= 1 << node_id;
+ connection_status.changed_nodes |= 1 << node_id;
+ connection_status.nodes[node_id] = network_node_id;
+ connection_status.total_nodes++;
+ connection_status_event->Signal();
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010442, nullptr, "Initialize (deprecated)"},
{0x00020000, nullptr, "Scrap"},
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index 39382ef09..a0b959797 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -152,7 +152,7 @@ void Init() {
auto gamecoin_result =
Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode);
if (gamecoin_result.Succeeded()) {
- auto gamecoin = gamecoin_result.MoveFrom();
+ auto gamecoin = std::move(gamecoin_result).Unwrap();
gamecoin->backend->Write(0, sizeof(GameCoin), true,
reinterpret_cast<const u8*>(&default_game_coin));
gamecoin->backend->Close();
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 791a65c19..aad950e50 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -173,8 +173,7 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
// TODO(yuriks): The kernel should be the one handling this as part of translation after
// everything else is migrated
- Kernel::HLERequestContext context;
- context.session = std::move(server_session);
+ Kernel::HLERequestContext context(std::move(server_session));
context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process,
Kernel::g_handle_table);
@@ -207,7 +206,7 @@ void AddService(Interface* interface_) {
auto server_port =
SM::g_service_manager
->RegisterService(interface_->GetPortName(), interface_->GetMaxSessions())
- .MoveFrom();
+ .Unwrap();
server_port->SetHleHandler(std::shared_ptr<Interface>(interface_));
}
diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp
index 74a1256e0..352941e69 100644
--- a/src/core/hle/service/sm/srv.cpp
+++ b/src/core/hle/service/sm/srv.cpp
@@ -113,13 +113,13 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
(*session)->GetObjectId());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(session.Code());
- rb.PushObjects(session.MoveFrom());
+ rb.PushObjects(std::move(session).Unwrap());
} else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && return_port_on_failure) {
LOG_WARNING(Service_SRV, "called service=%s -> ERR_MAX_CONNECTIONS_REACHED, *port*=%u",
name.c_str(), (*client_port)->GetObjectId());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ERR_MAX_CONNECTIONS_REACHED);
- rb.PushObjects(client_port.MoveFrom());
+ rb.PushObjects(std::move(client_port).Unwrap());
} else {
LOG_ERROR(Service_SRV, "called service=%s -> error 0x%08X", name.c_str(), session.Code());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index bb7bf2d67..e73971d5f 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -275,7 +275,7 @@ static void GetTransferEndEvent(Interface* self) {
cmd_buff[0] = IPC::MakeHeader(0xF, 2, 0);
cmd_buff[1] = RESULT_SUCCESS.raw;
- cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom();
+ cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).Unwrap();
LOG_DEBUG(Service_Y2R, "called");
}
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index e68b9f16a..c05401143 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -36,8 +36,9 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace SVC
-using Kernel::SharedPtr;
using Kernel::ERR_INVALID_HANDLE;
+using Kernel::Handle;
+using Kernel::SharedPtr;
namespace SVC {
@@ -933,7 +934,6 @@ static ResultCode CreatePort(Kernel::Handle* server_port, Kernel::Handle* client
using Kernel::ServerPort;
using Kernel::ClientPort;
- using Kernel::SharedPtr;
auto ports = ServerPort::CreatePortPair(max_sessions);
CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(
@@ -947,6 +947,41 @@ static ResultCode CreatePort(Kernel::Handle* server_port, Kernel::Handle* client
return RESULT_SUCCESS;
}
+static ResultCode CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) {
+ using Kernel::ClientPort;
+ SharedPtr<ClientPort> client_port = Kernel::g_handle_table.Get<ClientPort>(client_port_handle);
+ if (client_port == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ CASCADE_RESULT(auto session, client_port->Connect());
+ CASCADE_RESULT(*out_client_session, Kernel::g_handle_table.Create(std::move(session)));
+ return RESULT_SUCCESS;
+}
+
+static ResultCode CreateSession(Handle* server_session, Handle* client_session) {
+ auto sessions = Kernel::ServerSession::CreateSessionPair();
+
+ auto& server = std::get<SharedPtr<Kernel::ServerSession>>(sessions);
+ CASCADE_RESULT(*server_session, Kernel::g_handle_table.Create(std::move(server)));
+
+ auto& client = std::get<SharedPtr<Kernel::ClientSession>>(sessions);
+ CASCADE_RESULT(*client_session, Kernel::g_handle_table.Create(std::move(client)));
+
+ LOG_TRACE(Kernel_SVC, "called");
+ return RESULT_SUCCESS;
+}
+
+static ResultCode AcceptSession(Handle* out_server_session, Handle server_port_handle) {
+ using Kernel::ServerPort;
+ SharedPtr<ServerPort> server_port = Kernel::g_handle_table.Get<ServerPort>(server_port_handle);
+ if (server_port == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ CASCADE_RESULT(auto session, server_port->Accept());
+ CASCADE_RESULT(*out_server_session, Kernel::g_handle_table.Create(std::move(session)));
+ return RESULT_SUCCESS;
+}
+
static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
using Kernel::MemoryRegion;
@@ -1121,9 +1156,9 @@ static const FunctionDef SVC_Table[] = {
{0x45, nullptr, "Unknown"},
{0x46, nullptr, "Unknown"},
{0x47, HLE::Wrap<CreatePort>, "CreatePort"},
- {0x48, nullptr, "CreateSessionToPort"},
- {0x49, nullptr, "CreateSession"},
- {0x4A, nullptr, "AcceptSession"},
+ {0x48, HLE::Wrap<CreateSessionToPort>, "CreateSessionToPort"},
+ {0x49, HLE::Wrap<CreateSession>, "CreateSession"},
+ {0x4A, HLE::Wrap<AcceptSession>, "AcceptSession"},
{0x4B, nullptr, "ReplyAndReceive1"},
{0x4C, nullptr, "ReplyAndReceive2"},
{0x4D, nullptr, "ReplyAndReceive3"},