summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp5
-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/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/tests/CMakeLists.txt5
-rw-r--r--src/tests/core/hle/kernel/hle_ipc.cpp193
28 files changed, 299 insertions, 63 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 6cf1886cf..1cac1d0c9 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
23 boost::range::remove_erase(connected_sessions, server_session); 23 boost::range::remove_erase(connected_sessions, server_session);
24} 24}
25 25
26HLERequestContext::HLERequestContext(SharedPtr<ServerSession> session)
27 : session(std::move(session)) {
28 cmd_buf[0] = 0;
29}
30
26HLERequestContext::~HLERequestContext() = default; 31HLERequestContext::~HLERequestContext() = default;
27 32
28SharedPtr<Object> HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const { 33SharedPtr<Object> HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const {
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:
84 */ 84 */
85class HLERequestContext { 85class HLERequestContext {
86public: 86public:
87 HLERequestContext(SharedPtr<ServerSession> session);
87 ~HLERequestContext(); 88 ~HLERequestContext();
88 89
89 /// Returns a pointer to the IPC command buffer for this request. 90 /// Returns a pointer to the IPC command buffer for this request.
@@ -118,14 +119,14 @@ public:
118 */ 119 */
119 void ClearIncomingObjects(); 120 void ClearIncomingObjects();
120 121
121private: 122 /// Populates this context with data from the requesting process/thread.
122 friend class Service::ServiceFrameworkBase;
123
124 ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process, 123 ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process,
125 HandleTable& src_table); 124 HandleTable& src_table);
125 /// Writes data from this context back to the requesting process/thread.
126 ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process, 126 ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process,
127 HandleTable& dst_table) const; 127 HandleTable& dst_table) const;
128 128
129private:
129 std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; 130 std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
130 SharedPtr<ServerSession> session; 131 SharedPtr<ServerSession> session;
131 // TODO(yuriks): Check common usage of this and optimize size accordingly 132 // 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
166 auto vma = address_space 166 auto vma = address_space
167 .MapBackingMemory(mapping.address, target_pointer + offset_into_region, 167 .MapBackingMemory(mapping.address, target_pointer + offset_into_region,
168 mapping.size, memory_state) 168 mapping.size, memory_state)
169 .MoveFrom(); 169 .Unwrap();
170 address_space.Reprotect(vma, 170 address_space.Reprotect(vma,
171 mapping.read_only ? VMAPermission::Read : VMAPermission::ReadWrite); 171 mapping.read_only ? VMAPermission::Read : VMAPermission::ReadWrite);
172} 172}
@@ -176,14 +176,14 @@ void MapSharedPages(VMManager& address_space) {
176 .MapBackingMemory(Memory::CONFIG_MEMORY_VADDR, 176 .MapBackingMemory(Memory::CONFIG_MEMORY_VADDR,
177 reinterpret_cast<u8*>(&ConfigMem::config_mem), 177 reinterpret_cast<u8*>(&ConfigMem::config_mem),
178 Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared) 178 Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared)
179 .MoveFrom(); 179 .Unwrap();
180 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); 180 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
181 181
182 auto shared_page_vma = address_space 182 auto shared_page_vma = address_space
183 .MapBackingMemory(Memory::SHARED_PAGE_VADDR, 183 .MapBackingMemory(Memory::SHARED_PAGE_VADDR,
184 reinterpret_cast<u8*>(&SharedPage::shared_page), 184 reinterpret_cast<u8*>(&SharedPage::shared_page),
185 Memory::SHARED_PAGE_SIZE, MemoryState::Shared) 185 Memory::SHARED_PAGE_SIZE, MemoryState::Shared)
186 .MoveFrom(); 186 .Unwrap();
187 address_space.Reprotect(shared_page_vma, VMAPermission::Read); 187 address_space.Reprotect(shared_page_vma, VMAPermission::Read);
188} 188}
189 189
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() {
71 71
72ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name, 72ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name,
73 SharedPtr<ClientPort> port) { 73 SharedPtr<ClientPort> port) {
74 auto server_session = ServerSession::Create(name + "_Server").MoveFrom(); 74 auto server_session = ServerSession::Create(name + "_Server").Unwrap();
75 SharedPtr<ClientSession> client_session(new ClientSession); 75 SharedPtr<ClientSession> client_session(new ClientSession);
76 client_session->name = name + "_Client"; 76 client_session->name = name + "_Client";
77 77
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,
389 thread->wait_objects.clear(); 389 thread->wait_objects.clear();
390 thread->wait_address = 0; 390 thread->wait_address = 0;
391 thread->name = std::move(name); 391 thread->name = std::move(name);
392 thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom(); 392 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
393 thread->owner_process = g_current_process; 393 thread->owner_process = g_current_process;
394 394
395 // Find the next available TLS index, and mark it as used 395 // Find the next available TLS index, and mark it as used
@@ -484,7 +484,7 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
484 auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, 484 auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
485 Memory::HEAP_VADDR_END); 485 Memory::HEAP_VADDR_END);
486 486
487 SharedPtr<Thread> thread = thread_res.MoveFrom(); 487 SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
488 488
489 thread->context.fpscr = 489 thread->context.fpscr =
490 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 490 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) {
30 timer->name = std::move(name); 30 timer->name = std::move(name);
31 timer->initial_delay = 0; 31 timer->initial_delay = 0;
32 timer->interval_delay = 0; 32 timer->interval_delay = 0;
33 timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom(); 33 timer->callback_handle = timer_callback_handle_table.Create(timer).Unwrap();
34 34
35 return timer; 35 return timer;
36} 36}
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:
388 } 388 }
389 389
390 /// Asserts that the result succeeded and returns a reference to it. 390 /// Asserts that the result succeeded and returns a reference to it.
391 T& Unwrap() { 391 T& Unwrap() & {
392 ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); 392 ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
393 return **this; 393 return **this;
394 } 394 }
395 395
396 T&& MoveFrom() { 396 T&& Unwrap() && {
397 return std::move(Unwrap()); 397 ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
398 return std::move(**this);
398 } 399 }
399 400
400private: 401private:
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) {
55 u32 flags = rp.Pop<u32>(); 55 u32 flags = rp.Pop<u32>();
56 IPC::RequestBuilder rb = rp.MakeBuilder(1, 3); 56 IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
57 rb.Push(RESULT_SUCCESS); 57 rb.Push(RESULT_SUCCESS);
58 rb.PushCopyHandles(Kernel::g_handle_table.Create(notification_event).MoveFrom(), 58 rb.PushCopyHandles(Kernel::g_handle_table.Create(notification_event).Unwrap(),
59 Kernel::g_handle_table.Create(parameter_event).MoveFrom()); 59 Kernel::g_handle_table.Create(parameter_event).Unwrap());
60 60
61 // TODO(bunnei): Check if these events are cleared every time Initialize is called. 61 // TODO(bunnei): Check if these events are cleared every time Initialize is called.
62 notification_event->Clear(); 62 notification_event->Clear();
@@ -93,7 +93,7 @@ void GetSharedFont(Service::Interface* self) {
93 // allocated, the real APT service calculates this address by scanning the entire address space 93 // allocated, the real APT service calculates this address by scanning the entire address space
94 // (using svcQueryMemory) and searches for an allocation of the same size as the Shared Font. 94 // (using svcQueryMemory) and searches for an allocation of the same size as the Shared Font.
95 rb.Push(target_address); 95 rb.Push(target_address);
96 rb.PushCopyHandles(Kernel::g_handle_table.Create(shared_font_mem).MoveFrom()); 96 rb.PushCopyHandles(Kernel::g_handle_table.Create(shared_font_mem).Unwrap());
97} 97}
98 98
99void NotifyToWait(Service::Interface* self) { 99void NotifyToWait(Service::Interface* self) {
@@ -115,7 +115,7 @@ void GetLockHandle(Service::Interface* self) {
115 rb.Push(RESULT_SUCCESS); // No error 115 rb.Push(RESULT_SUCCESS); // No error
116 rb.Push(applet_attributes); // Applet Attributes, this value is passed to Enable. 116 rb.Push(applet_attributes); // Applet Attributes, this value is passed to Enable.
117 rb.Push<u32>(0); // Least significant bit = power button state 117 rb.Push<u32>(0); // Least significant bit = power button state
118 Kernel::Handle handle_copy = Kernel::g_handle_table.Create(lock).MoveFrom(); 118 Kernel::Handle handle_copy = Kernel::g_handle_table.Create(lock).Unwrap();
119 rb.PushCopyHandles(handle_copy); 119 rb.PushCopyHandles(handle_copy);
120 120
121 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", handle_copy, 121 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", handle_copy,
@@ -231,7 +231,7 @@ void ReceiveParameter(Service::Interface* self) {
231 rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size 231 rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size
232 232
233 rb.PushMoveHandles((next_parameter.object != nullptr) 233 rb.PushMoveHandles((next_parameter.object != nullptr)
234 ? Kernel::g_handle_table.Create(next_parameter.object).MoveFrom() 234 ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap()
235 : 0); 235 : 0);
236 rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0); 236 rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0);
237 237
@@ -261,7 +261,7 @@ void GlanceParameter(Service::Interface* self) {
261 rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size 261 rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size
262 262
263 rb.PushCopyHandles((next_parameter.object != nullptr) 263 rb.PushCopyHandles((next_parameter.object != nullptr)
264 ? Kernel::g_handle_table.Create(next_parameter.object).MoveFrom() 264 ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap()
265 : 0); 265 : 0);
266 rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0); 266 rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0);
267 267
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) {
347 int port = *port_select.begin(); 347 int port = *port_select.begin();
348 rb.Push(RESULT_SUCCESS); 348 rb.Push(RESULT_SUCCESS);
349 rb.PushCopyHandles( 349 rb.PushCopyHandles(
350 Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).MoveFrom()); 350 Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).Unwrap());
351 } else { 351 } else {
352 LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); 352 LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val);
353 rb.Push(ERROR_INVALID_ENUM_VALUE); 353 rb.Push(ERROR_INVALID_ENUM_VALUE);
@@ -366,7 +366,7 @@ void GetBufferErrorInterruptEvent(Service::Interface* self) {
366 int port = *port_select.begin(); 366 int port = *port_select.begin();
367 rb.Push(RESULT_SUCCESS); 367 rb.Push(RESULT_SUCCESS);
368 rb.PushCopyHandles( 368 rb.PushCopyHandles(
369 Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).MoveFrom()); 369 Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).Unwrap());
370 } else { 370 } else {
371 LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); 371 LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val);
372 rb.Push(ERROR_INVALID_ENUM_VALUE); 372 rb.Push(ERROR_INVALID_ENUM_VALUE);
@@ -400,7 +400,7 @@ void SetReceiving(Service::Interface* self) {
400 } 400 }
401 401
402 rb.Push(RESULT_SUCCESS); 402 rb.Push(RESULT_SUCCESS);
403 rb.PushCopyHandles(Kernel::g_handle_table.Create(port.completion_event).MoveFrom()); 403 rb.PushCopyHandles(Kernel::g_handle_table.Create(port.completion_event).Unwrap());
404 } else { 404 } else {
405 LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); 405 LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val);
406 rb.Push(ERROR_INVALID_ENUM_VALUE); 406 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) {
31void GetCecInfoEventHandle(Service::Interface* self) { 31void GetCecInfoEventHandle(Service::Interface* self) {
32 u32* cmd_buff = Kernel::GetCommandBuffer(); 32 u32* cmd_buff = Kernel::GetCommandBuffer();
33 33
34 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 34 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
35 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle 35 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).Unwrap(); // Event handle
36 36
37 LOG_WARNING(Service_CECD, "(STUBBED) called"); 37 LOG_WARNING(Service_CECD, "(STUBBED) called");
38} 38}
@@ -40,8 +40,8 @@ void GetCecInfoEventHandle(Service::Interface* self) {
40void GetChangeStateEventHandle(Service::Interface* self) { 40void GetChangeStateEventHandle(Service::Interface* self) {
41 u32* cmd_buff = Kernel::GetCommandBuffer(); 41 u32* cmd_buff = Kernel::GetCommandBuffer();
42 42
43 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 43 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
44 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle 44 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).Unwrap(); // Event handle
45 45
46 LOG_WARNING(Service_CECD, "(STUBBED) called"); 46 LOG_WARNING(Service_CECD, "(STUBBED) called");
47} 47}
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() {
406 auto config_result = Service::FS::OpenFileFromArchive(cfg_system_save_data_archive, path, mode); 406 auto config_result = Service::FS::OpenFileFromArchive(cfg_system_save_data_archive, path, mode);
407 ASSERT_MSG(config_result.Succeeded(), "could not open file"); 407 ASSERT_MSG(config_result.Succeeded(), "could not open file");
408 408
409 auto config = config_result.MoveFrom(); 409 auto config = std::move(config_result).Unwrap();
410 config->backend->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data()); 410 config->backend->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data());
411 411
412 return RESULT_SUCCESS; 412 return RESULT_SUCCESS;
@@ -560,7 +560,7 @@ ResultCode LoadConfigNANDSaveFile() {
560 560
561 // Read the file if it already exists 561 // Read the file if it already exists
562 if (config_result.Succeeded()) { 562 if (config_result.Succeeded()) {
563 auto config = config_result.MoveFrom(); 563 auto config = std::move(config_result).Unwrap();
564 config->backend->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); 564 config->backend->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data());
565 return RESULT_SUCCESS; 565 return RESULT_SUCCESS;
566 } 566 }
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) {
51 51
52 cmd_buff[1] = RESULT_SUCCESS.raw; 52 cmd_buff[1] = RESULT_SUCCESS.raw;
53 cmd_buff[2] = IPC::CopyHandleDesc(2); 53 cmd_buff[2] = IPC::CopyHandleDesc(2);
54 cmd_buff[3] = Kernel::g_handle_table.Create(mutex).MoveFrom(); 54 cmd_buff[3] = Kernel::g_handle_table.Create(mutex).Unwrap();
55 cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).MoveFrom(); 55 cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).Unwrap();
56 56
57 LOG_WARNING(Service_CSND, "(STUBBED) called"); 57 LOG_WARNING(Service_CSND, "(STUBBED) called");
58} 58}
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) {
168 cmd_buff[0] = IPC::MakeHeader(0x16, 1, 2); 168 cmd_buff[0] = IPC::MakeHeader(0x16, 1, 2);
169 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 169 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
170 // cmd_buff[2] not set 170 // cmd_buff[2] not set
171 cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle 171 cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).Unwrap(); // Event handle
172 172
173 LOG_WARNING(Service_DSP, "(STUBBED) called"); 173 LOG_WARNING(Service_DSP, "(STUBBED) called");
174} 174}
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
311 if (backend.Failed()) 311 if (backend.Failed())
312 return backend.Code(); 312 return backend.Code();
313 313
314 auto file = std::shared_ptr<File>(new File(backend.MoveFrom(), path)); 314 auto file = std::shared_ptr<File>(new File(std::move(backend).Unwrap(), path));
315 return MakeResult<std::shared_ptr<File>>(std::move(file)); 315 return MakeResult<std::shared_ptr<File>>(std::move(file));
316} 316}
317 317
@@ -401,7 +401,7 @@ ResultVal<std::shared_ptr<Directory>> OpenDirectoryFromArchive(ArchiveHandle arc
401 if (backend.Failed()) 401 if (backend.Failed())
402 return backend.Code(); 402 return backend.Code();
403 403
404 auto directory = std::shared_ptr<Directory>(new Directory(backend.MoveFrom(), path)); 404 auto directory = std::shared_ptr<Directory>(new Directory(std::move(backend).Unwrap(), path));
405 return MakeResult<std::shared_ptr<Directory>>(std::move(directory)); 405 return MakeResult<std::shared_ptr<Directory>>(std::move(directory));
406} 406}
407 407
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) {
87 file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); 87 file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
88 88
89 rb.PushMoveHandles( 89 rb.PushMoveHandles(
90 Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom()); 90 Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).Unwrap());
91 } else { 91 } else {
92 rb.PushMoveHandles(0); 92 rb.PushMoveHandles(0);
93 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 93 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) {
153 file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); 153 file->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
154 154
155 cmd_buff[3] = 155 cmd_buff[3] =
156 Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom(); 156 Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).Unwrap();
157 } else { 157 } else {
158 cmd_buff[3] = 0; 158 cmd_buff[3] = 0;
159 LOG_ERROR(Service_FS, "failed to get a handle for file %s mode=%u attributes=%u", 159 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) {
420 directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); 420 directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
421 421
422 cmd_buff[3] = 422 cmd_buff[3] =
423 Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).MoveFrom(); 423 Kernel::g_handle_table.Create(std::get<SharedPtr<ClientSession>>(sessions)).Unwrap();
424 } else { 424 } else {
425 LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s", 425 LOG_ERROR(Service_FS, "failed to get a handle for directory type=%d size=%d data=%s",
426 dirname_type, dirname_size, dir_path.DebugStr().c_str()); 426 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) {
389 } else { 389 } else {
390 cmd_buff[1] = RESULT_SUCCESS.raw; 390 cmd_buff[1] = RESULT_SUCCESS.raw;
391 } 391 }
392 cmd_buff[2] = g_thread_id++; // Thread ID 392 cmd_buff[2] = g_thread_id++; // Thread ID
393 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory 393 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).Unwrap(); // GSP shared memory
394 394
395 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? 395 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct?
396 396
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) {
253 cmd_buff[1] = 0; // No error 253 cmd_buff[1] = 0; // No error
254 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header 254 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
255 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) 255 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
256 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom(); 256 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).Unwrap();
257 cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).MoveFrom(); 257 cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).Unwrap();
258 cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_2).MoveFrom(); 258 cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_2).Unwrap();
259 cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::event_accelerometer).MoveFrom(); 259 cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::event_accelerometer).Unwrap();
260 cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::event_gyroscope).MoveFrom(); 260 cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::event_gyroscope).Unwrap();
261 cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).MoveFrom(); 261 cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).Unwrap();
262} 262}
263 263
264void EnableAccelerometer(Service::Interface* self) { 264void 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) {
145 IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 0, 0); 145 IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 0, 0);
146 IPC::RequestBuilder rb = rp.MakeBuilder(1, 3); 146 IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
147 rb.Push(RESULT_SUCCESS); 147 rb.Push(RESULT_SUCCESS);
148 rb.PushMoveHandles(Kernel::g_handle_table.Create(Service::IR::shared_memory).MoveFrom(), 148 rb.PushMoveHandles(Kernel::g_handle_table.Create(Service::IR::shared_memory).Unwrap(),
149 Kernel::g_handle_table.Create(Service::IR::update_event).MoveFrom()); 149 Kernel::g_handle_table.Create(Service::IR::update_event).Unwrap());
150} 150}
151 151
152/** 152/**
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) {
337 IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0A, 1, 2); 337 IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0A, 1, 2);
338 338
339 rb.Push(RESULT_SUCCESS); 339 rb.Push(RESULT_SUCCESS);
340 rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::receive_event).MoveFrom()); 340 rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::receive_event).Unwrap());
341 341
342 LOG_INFO(Service_IR, "called"); 342 LOG_INFO(Service_IR, "called");
343} 343}
@@ -354,7 +354,7 @@ void GetSendEvent(Interface* self) {
354 IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0B, 1, 2); 354 IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0B, 1, 2);
355 355
356 rb.Push(RESULT_SUCCESS); 356 rb.Push(RESULT_SUCCESS);
357 rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::send_event).MoveFrom()); 357 rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::send_event).Unwrap());
358 358
359 LOG_INFO(Service_IR, "called"); 359 LOG_INFO(Service_IR, "called");
360} 360}
@@ -394,7 +394,7 @@ static void GetConnectionStatusEvent(Interface* self) {
394 IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0C, 1, 2); 394 IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0C, 1, 2);
395 395
396 rb.Push(RESULT_SUCCESS); 396 rb.Push(RESULT_SUCCESS);
397 rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::conn_status_event).MoveFrom()); 397 rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::conn_status_event).Unwrap());
398 398
399 LOG_INFO(Service_IR, "called"); 399 LOG_INFO(Service_IR, "called");
400} 400}
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) {
160static void GetBufferFullEvent(Interface* self) { 160static void GetBufferFullEvent(Interface* self) {
161 u32* cmd_buff = Kernel::GetCommandBuffer(); 161 u32* cmd_buff = Kernel::GetCommandBuffer();
162 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 162 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
163 cmd_buff[3] = Kernel::g_handle_table.Create(buffer_full_event).MoveFrom(); 163 cmd_buff[3] = Kernel::g_handle_table.Create(buffer_full_event).Unwrap();
164 LOG_WARNING(Service_MIC, "(STUBBED) called"); 164 LOG_WARNING(Service_MIC, "(STUBBED) called");
165} 165}
166 166
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) {
95 cmd_buff[0] = IPC::MakeHeader(0xB, 1, 2); 95 cmd_buff[0] = IPC::MakeHeader(0xB, 1, 2);
96 cmd_buff[1] = RESULT_SUCCESS.raw; 96 cmd_buff[1] = RESULT_SUCCESS.raw;
97 cmd_buff[2] = IPC::CopyHandleDesc(); 97 cmd_buff[2] = IPC::CopyHandleDesc();
98 cmd_buff[3] = Kernel::g_handle_table.Create(tag_in_range_event).MoveFrom(); 98 cmd_buff[3] = Kernel::g_handle_table.Create(tag_in_range_event).Unwrap();
99 LOG_WARNING(Service_NFC, "(STUBBED) called"); 99 LOG_WARNING(Service_NFC, "(STUBBED) called");
100} 100}
101 101
@@ -105,7 +105,7 @@ void GetTagOutOfRangeEvent(Interface* self) {
105 cmd_buff[0] = IPC::MakeHeader(0xC, 1, 2); 105 cmd_buff[0] = IPC::MakeHeader(0xC, 1, 2);
106 cmd_buff[1] = RESULT_SUCCESS.raw; 106 cmd_buff[1] = RESULT_SUCCESS.raw;
107 cmd_buff[2] = IPC::CopyHandleDesc(); 107 cmd_buff[2] = IPC::CopyHandleDesc();
108 cmd_buff[3] = Kernel::g_handle_table.Create(tag_out_of_range_event).MoveFrom(); 108 cmd_buff[3] = Kernel::g_handle_table.Create(tag_out_of_range_event).Unwrap();
109 LOG_WARNING(Service_NFC, "(STUBBED) called"); 109 LOG_WARNING(Service_NFC, "(STUBBED) called");
110} 110}
111 111
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp
index e92900d48..a7149c9e8 100644
--- a/src/core/hle/service/nwm/nwm_uds.cpp
+++ b/src/core/hle/service/nwm/nwm_uds.cpp
@@ -190,7 +190,7 @@ static void InitializeWithVersion(Interface* self) {
190 190
191 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); 191 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
192 rb.Push(RESULT_SUCCESS); 192 rb.Push(RESULT_SUCCESS);
193 rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).MoveFrom()); 193 rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).Unwrap());
194 194
195 LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X", 195 LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X",
196 sharedmem_size, version, sharedmem_handle); 196 sharedmem_size, version, sharedmem_handle);
@@ -265,7 +265,7 @@ static void Bind(Interface* self) {
265 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); 265 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
266 266
267 rb.Push(RESULT_SUCCESS); 267 rb.Push(RESULT_SUCCESS);
268 rb.PushCopyHandles(Kernel::g_handle_table.Create(event).MoveFrom()); 268 rb.PushCopyHandles(Kernel::g_handle_table.Create(event).Unwrap());
269} 269}
270 270
271/** 271/**
@@ -543,6 +543,42 @@ static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
543 beacon_broadcast_event, 0); 543 beacon_broadcast_event, 0);
544} 544}
545 545
546/*
547 * Returns an available index in the nodes array for the
548 * currently-hosted UDS network.
549 */
550static u32 GetNextAvailableNodeId() {
551 ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
552 "Can not accept clients if we're not hosting a network");
553
554 for (unsigned index = 0; index < connection_status.max_nodes; ++index) {
555 if ((connection_status.node_bitmask & (1 << index)) == 0)
556 return index;
557 }
558
559 // Any connection attempts to an already full network should have been refused.
560 ASSERT_MSG(false, "No available connection slots in the network");
561}
562
563/*
564 * Called when a client connects to an UDS network we're hosting,
565 * updates the connection status and signals the update event.
566 * @param network_node_id Network Node Id of the connecting client.
567 */
568void OnClientConnected(u16 network_node_id) {
569 ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
570 "Can not accept clients if we're not hosting a network");
571 ASSERT_MSG(connection_status.total_nodes < connection_status.max_nodes,
572 "Can not accept connections on a full network");
573
574 u32 node_id = GetNextAvailableNodeId();
575 connection_status.node_bitmask |= 1 << node_id;
576 connection_status.changed_nodes |= 1 << node_id;
577 connection_status.nodes[node_id] = network_node_id;
578 connection_status.total_nodes++;
579 connection_status_event->Signal();
580}
581
546const Interface::FunctionInfo FunctionTable[] = { 582const Interface::FunctionInfo FunctionTable[] = {
547 {0x00010442, nullptr, "Initialize (deprecated)"}, 583 {0x00010442, nullptr, "Initialize (deprecated)"},
548 {0x00020000, nullptr, "Scrap"}, 584 {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() {
152 auto gamecoin_result = 152 auto gamecoin_result =
153 Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); 153 Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode);
154 if (gamecoin_result.Succeeded()) { 154 if (gamecoin_result.Succeeded()) {
155 auto gamecoin = gamecoin_result.MoveFrom(); 155 auto gamecoin = std::move(gamecoin_result).Unwrap();
156 gamecoin->backend->Write(0, sizeof(GameCoin), true, 156 gamecoin->backend->Write(0, sizeof(GameCoin), true,
157 reinterpret_cast<const u8*>(&default_game_coin)); 157 reinterpret_cast<const u8*>(&default_game_coin));
158 gamecoin->backend->Close(); 158 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
173 173
174 // TODO(yuriks): The kernel should be the one handling this as part of translation after 174 // TODO(yuriks): The kernel should be the one handling this as part of translation after
175 // everything else is migrated 175 // everything else is migrated
176 Kernel::HLERequestContext context; 176 Kernel::HLERequestContext context(std::move(server_session));
177 context.session = std::move(server_session);
178 context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process, 177 context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process,
179 Kernel::g_handle_table); 178 Kernel::g_handle_table);
180 179
@@ -207,7 +206,7 @@ void AddService(Interface* interface_) {
207 auto server_port = 206 auto server_port =
208 SM::g_service_manager 207 SM::g_service_manager
209 ->RegisterService(interface_->GetPortName(), interface_->GetMaxSessions()) 208 ->RegisterService(interface_->GetPortName(), interface_->GetMaxSessions())
210 .MoveFrom(); 209 .Unwrap();
211 server_port->SetHleHandler(std::shared_ptr<Interface>(interface_)); 210 server_port->SetHleHandler(std::shared_ptr<Interface>(interface_));
212} 211}
213 212
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) {
113 (*session)->GetObjectId()); 113 (*session)->GetObjectId());
114 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); 114 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
115 rb.Push(session.Code()); 115 rb.Push(session.Code());
116 rb.PushObjects(session.MoveFrom()); 116 rb.PushObjects(std::move(session).Unwrap());
117 } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && return_port_on_failure) { 117 } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && return_port_on_failure) {
118 LOG_WARNING(Service_SRV, "called service=%s -> ERR_MAX_CONNECTIONS_REACHED, *port*=%u", 118 LOG_WARNING(Service_SRV, "called service=%s -> ERR_MAX_CONNECTIONS_REACHED, *port*=%u",
119 name.c_str(), (*client_port)->GetObjectId()); 119 name.c_str(), (*client_port)->GetObjectId());
120 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); 120 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
121 rb.Push(ERR_MAX_CONNECTIONS_REACHED); 121 rb.Push(ERR_MAX_CONNECTIONS_REACHED);
122 rb.PushObjects(client_port.MoveFrom()); 122 rb.PushObjects(std::move(client_port).Unwrap());
123 } else { 123 } else {
124 LOG_ERROR(Service_SRV, "called service=%s -> error 0x%08X", name.c_str(), session.Code()); 124 LOG_ERROR(Service_SRV, "called service=%s -> error 0x%08X", name.c_str(), session.Code());
125 IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); 125 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) {
275 275
276 cmd_buff[0] = IPC::MakeHeader(0xF, 2, 0); 276 cmd_buff[0] = IPC::MakeHeader(0xF, 2, 0);
277 cmd_buff[1] = RESULT_SUCCESS.raw; 277 cmd_buff[1] = RESULT_SUCCESS.raw;
278 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom(); 278 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).Unwrap();
279 279
280 LOG_DEBUG(Service_Y2R, "called"); 280 LOG_DEBUG(Service_Y2R, "called");
281} 281}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 00d7c636a..a14df325a 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -1,8 +1,9 @@
1set(SRCS 1set(SRCS
2 glad.cpp
3 tests.cpp
4 common/param_package.cpp 2 common/param_package.cpp
5 core/file_sys/path_parser.cpp 3 core/file_sys/path_parser.cpp
4 core/hle/kernel/hle_ipc.cpp
5 glad.cpp
6 tests.cpp
6 ) 7 )
7 8
8set(HEADERS 9set(HEADERS
diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp
new file mode 100644
index 000000000..e07a28c5b
--- /dev/null
+++ b/src/tests/core/hle/kernel/hle_ipc.cpp
@@ -0,0 +1,193 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <catch.hpp>
6#include "core/hle/ipc.h"
7#include "core/hle/kernel/client_port.h"
8#include "core/hle/kernel/client_session.h"
9#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/hle_ipc.h"
12#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/server_session.h"
14
15namespace Kernel {
16
17static SharedPtr<Object> MakeObject() {
18 return Event::Create(ResetType::OneShot);
19}
20
21TEST_CASE("HLERequestContext::PopoulateFromIncomingCommandBuffer", "[core][kernel]") {
22 auto session = std::get<SharedPtr<ServerSession>>(ServerSession::CreateSessionPair());
23 HLERequestContext context(std::move(session));
24
25 auto process = Process::Create(CodeSet::Create("", 0));
26 HandleTable handle_table;
27
28 SECTION("works with empty cmdbuf") {
29 const u32_le input[]{
30 IPC::MakeHeader(0x1234, 0, 0),
31 };
32
33 context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
34
35 REQUIRE(context.CommandBuffer()[0] == 0x12340000);
36 }
37
38 SECTION("translates regular params") {
39 const u32_le input[]{
40 IPC::MakeHeader(0, 3, 0), 0x12345678, 0x21122112, 0xAABBCCDD,
41 };
42
43 context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
44
45 auto* output = context.CommandBuffer();
46 REQUIRE(output[1] == 0x12345678);
47 REQUIRE(output[2] == 0x21122112);
48 REQUIRE(output[3] == 0xAABBCCDD);
49 }
50
51 SECTION("translates move handles") {
52 auto a = MakeObject();
53 Handle a_handle = handle_table.Create(a).Unwrap();
54 const u32_le input[]{
55 IPC::MakeHeader(0, 0, 2), IPC::MoveHandleDesc(1), a_handle,
56 };
57
58 context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
59
60 auto* output = context.CommandBuffer();
61 REQUIRE(context.GetIncomingHandle(output[2]) == a);
62 REQUIRE(handle_table.GetGeneric(a_handle) == nullptr);
63 }
64
65 SECTION("translates copy handles") {
66 auto a = MakeObject();
67 Handle a_handle = handle_table.Create(a).Unwrap();
68 const u32_le input[]{
69 IPC::MakeHeader(0, 0, 2), IPC::CopyHandleDesc(1), a_handle,
70 };
71
72 context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
73
74 auto* output = context.CommandBuffer();
75 REQUIRE(context.GetIncomingHandle(output[2]) == a);
76 REQUIRE(handle_table.GetGeneric(a_handle) == a);
77 }
78
79 SECTION("translates multi-handle descriptors") {
80 auto a = MakeObject();
81 auto b = MakeObject();
82 auto c = MakeObject();
83 const u32_le input[]{
84 IPC::MakeHeader(0, 0, 5), IPC::MoveHandleDesc(2),
85 handle_table.Create(a).Unwrap(), handle_table.Create(b).Unwrap(),
86 IPC::MoveHandleDesc(1), handle_table.Create(c).Unwrap(),
87 };
88
89 context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
90
91 auto* output = context.CommandBuffer();
92 REQUIRE(context.GetIncomingHandle(output[2]) == a);
93 REQUIRE(context.GetIncomingHandle(output[3]) == b);
94 REQUIRE(context.GetIncomingHandle(output[5]) == c);
95 }
96
97 SECTION("translates CallingPid descriptors") {
98 const u32_le input[]{
99 IPC::MakeHeader(0, 0, 2), IPC::CallingPidDesc(), 0x98989898,
100 };
101
102 context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
103
104 REQUIRE(context.CommandBuffer()[2] == process->process_id);
105 }
106
107 SECTION("translates mixed params") {
108 auto a = MakeObject();
109 const u32_le input[]{
110 IPC::MakeHeader(0, 2, 4),
111 0x12345678,
112 0xABCDEF00,
113 IPC::MoveHandleDesc(1),
114 handle_table.Create(a).Unwrap(),
115 IPC::CallingPidDesc(),
116 0,
117 };
118
119 context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
120
121 auto* output = context.CommandBuffer();
122 REQUIRE(output[1] == 0x12345678);
123 REQUIRE(output[2] == 0xABCDEF00);
124 REQUIRE(context.GetIncomingHandle(output[4]) == a);
125 REQUIRE(output[6] == process->process_id);
126 }
127}
128
129TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
130 auto session = std::get<SharedPtr<ServerSession>>(ServerSession::CreateSessionPair());
131 HLERequestContext context(std::move(session));
132
133 auto process = Process::Create(CodeSet::Create("", 0));
134 HandleTable handle_table;
135 auto* input = context.CommandBuffer();
136 u32_le output[IPC::COMMAND_BUFFER_LENGTH];
137
138 SECTION("works with empty cmdbuf") {
139 input[0] = IPC::MakeHeader(0x1234, 0, 0);
140
141 context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
142
143 REQUIRE(output[0] == 0x12340000);
144 }
145
146 SECTION("translates regular params") {
147 input[0] = IPC::MakeHeader(0, 3, 0);
148 input[1] = 0x12345678;
149 input[2] = 0x21122112;
150 input[3] = 0xAABBCCDD;
151
152 context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
153
154 REQUIRE(output[1] == 0x12345678);
155 REQUIRE(output[2] == 0x21122112);
156 REQUIRE(output[3] == 0xAABBCCDD);
157 }
158
159 SECTION("translates move/copy handles") {
160 auto a = MakeObject();
161 auto b = MakeObject();
162 input[0] = IPC::MakeHeader(0, 0, 4);
163 input[1] = IPC::MoveHandleDesc(1);
164 input[2] = context.AddOutgoingHandle(a);
165 input[3] = IPC::CopyHandleDesc(1);
166 input[4] = context.AddOutgoingHandle(b);
167
168 context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
169
170 REQUIRE(handle_table.GetGeneric(output[2]) == a);
171 REQUIRE(handle_table.GetGeneric(output[4]) == b);
172 }
173
174 SECTION("translates multi-handle descriptors") {
175 auto a = MakeObject();
176 auto b = MakeObject();
177 auto c = MakeObject();
178 input[0] = IPC::MakeHeader(0, 0, 5);
179 input[1] = IPC::MoveHandleDesc(2);
180 input[2] = context.AddOutgoingHandle(a);
181 input[3] = context.AddOutgoingHandle(b);
182 input[4] = IPC::CopyHandleDesc(1);
183 input[5] = context.AddOutgoingHandle(c);
184
185 context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
186
187 REQUIRE(handle_table.GetGeneric(output[2]) == a);
188 REQUIRE(handle_table.GetGeneric(output[3]) == b);
189 REQUIRE(handle_table.GetGeneric(output[5]) == c);
190 }
191}
192
193} // namespace Kernel