From d15cadd760c71bb5fcf82a12bc8b0de2e23bae95 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Wed, 17 Jan 2018 01:09:33 -0500
Subject: [PATCH 1/3] loggin: Add IPC logging category.

---
 src/common/logging/backend.cpp | 3 ++-
 src/common/logging/log.h       | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 13f915a017..ba0acfb72d 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -43,6 +43,7 @@ namespace Log {
     SUB(HW, LCD)                                                                                   \
     SUB(HW, GPU)                                                                                   \
     SUB(HW, AES)                                                                                   \
+    CLS(IPC)                                                                                       \
     CLS(Frontend)                                                                                  \
     CLS(Render)                                                                                    \
     SUB(Render, Software)                                                                          \
@@ -91,8 +92,8 @@ const char* GetLevelName(Level log_level) {
 
 Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
                   const char* function, const char* format, va_list args) {
-    using std::chrono::steady_clock;
     using std::chrono::duration_cast;
+    using std::chrono::steady_clock;
 
     static steady_clock::time_point time_origin = steady_clock::now();
 
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 35b5af3cba..57021037a4 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -60,6 +60,7 @@ enum class Class : ClassType {
     HW_LCD,            ///< LCD register emulation
     HW_GPU,            ///< GPU control emulation
     HW_AES,            ///< AES engine emulation
+    IPC,               ///< IPC interface
     Frontend,          ///< Emulator UI
     Render,            ///< Emulator video output and hardware acceleration
     Render_Software,   ///< Software renderer backend

From 30cb98f874d0df9e818976f2140135ac8fe1501b Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Wed, 17 Jan 2018 01:16:55 -0500
Subject: [PATCH 2/3] ipc: Implement domain command CloseVirtualHandle.

---
 src/core/hle/ipc.h              |  7 ++++++-
 src/core/hle/kernel/domain.cpp  | 21 ++++++++++++++++++++-
 src/core/hle/kernel/hle_ipc.cpp |  9 ++++++++-
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h
index 88ba105e50..1840fac12c 100644
--- a/src/core/hle/ipc.h
+++ b/src/core/hle/ipc.h
@@ -143,6 +143,11 @@ struct DataPayloadHeader {
 static_assert(sizeof(DataPayloadHeader) == 8, "DataPayloadRequest size is incorrect");
 
 struct DomainMessageHeader {
+    enum class CommandType : u32_le {
+        SendMessage = 1,
+        CloseVirtualHandle = 2,
+    };
+
     union {
         // Used when responding to an IPC request, Server -> Client.
         struct {
@@ -153,7 +158,7 @@ struct DomainMessageHeader {
         // Used when performing an IPC request, Client -> Server.
         struct {
             union {
-                BitField<0, 8, u32_le> command;
+                BitField<0, 8, CommandType> command;
                 BitField<16, 16, u32_le> size;
             };
             u32_le object_id;
diff --git a/src/core/hle/kernel/domain.cpp b/src/core/hle/kernel/domain.cpp
index 7ebb4b9c74..5035e9c083 100644
--- a/src/core/hle/kernel/domain.cpp
+++ b/src/core/hle/kernel/domain.cpp
@@ -2,6 +2,8 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/domain.h"
 #include "core/hle/kernel/handle_table.h"
@@ -36,7 +38,24 @@ ResultCode Domain::SendSyncRequest(SharedPtr<Thread> thread) {
     if (domain_message_header) {
         // If there is a DomainMessageHeader, then this is CommandType "Request"
         const u32 object_id{context.GetDomainMessageHeader()->object_id};
-        return request_handlers[object_id - 1]->HandleSyncRequest(context);
+        switch (domain_message_header->command) {
+        case IPC::DomainMessageHeader::CommandType::SendMessage:
+            return request_handlers[object_id - 1]->HandleSyncRequest(context);
+
+        case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
+            LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id);
+
+            request_handlers[object_id - 1] = nullptr;
+
+            IPC::RequestBuilder rb{context, 2};
+            rb.Push(RESULT_SUCCESS);
+
+            return RESULT_SUCCESS;
+        }
+        }
+
+        LOG_CRITICAL(IPC, "Unknown domain command=%d", domain_message_header->command.Value());
+        UNIMPLEMENTED();
     }
     return request_handlers.front()->HandleSyncRequest(context);
 }
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index afa09b404a..2ccc242f67 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -102,13 +102,20 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
     data_payload_header =
         std::make_unique<IPC::DataPayloadHeader>(rp.PopRaw<IPC::DataPayloadHeader>());
 
+    data_payload_offset = rp.GetCurrentOffset();
+
+    if (domain_message_header && domain_message_header->command ==
+                                     IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) {
+        // CloseVirtualHandle command does not have SFC* or any data
+        return;
+    }
+
     if (incoming) {
         ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I'));
     } else {
         ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O'));
     }
 
-    data_payload_offset = rp.GetCurrentOffset();
     command = rp.Pop<u32_le>();
     rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
 }

From b588cbcb1dd1c4256c6d0011a424af9d888ecb20 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Wed, 17 Jan 2018 11:37:26 -0500
Subject: [PATCH 3/3] hle_ipc: Clang format.

---
 src/core/hle/kernel/hle_ipc.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 2ccc242f67..ac62a0d5af 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -104,8 +104,9 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
 
     data_payload_offset = rp.GetCurrentOffset();
 
-    if (domain_message_header && domain_message_header->command ==
-                                     IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) {
+    if (domain_message_header &&
+        domain_message_header->command ==
+            IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) {
         // CloseVirtualHandle command does not have SFC* or any data
         return;
     }