From 2e13b7f3ca9e7ecf0b0b6c1da65453e46ee6728f Mon Sep 17 00:00:00 2001
From: mailwl <mailwl@gmail.com>
Date: Sun, 21 Feb 2016 14:48:28 +0300
Subject: [PATCH] Initial implementation ir:user

---
 src/common/logging/backend.cpp      |  1 +
 src/common/logging/log.h            |  1 +
 src/core/hle/service/ir/ir.cpp      | 72 +++++++++++++++++++++++++++--
 src/core/hle/service/ir/ir.h        | 47 +++++++++++++++++++
 src/core/hle/service/ir/ir_user.cpp | 41 ++++++++++------
 5 files changed, 144 insertions(+), 18 deletions(-)

diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 58819012d8..54291429a0 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -49,6 +49,7 @@ namespace Log {
         SUB(Service, DSP) \
         SUB(Service, HID) \
         SUB(Service, SOC) \
+        SUB(Service, IR) \
         SUB(Service, Y2R) \
         CLS(HW) \
         SUB(HW, Memory) \
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index ec7bb00b8c..4b01805ae9 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -64,6 +64,7 @@ enum class Class : ClassType {
     Service_DSP,                ///< The DSP (DSP control) service
     Service_HID,                ///< The HID (Human interface device) service
     Service_SOC,                ///< The SOC (Socket) service
+    Service_IR,                 ///< The IR service
     Service_Y2R,                ///< The Y2R (YUV to RGB conversion) service
     HW,                         ///< Low-level hardware emulation
     HW_Memory,                  ///< Memory-map and address translation
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp
index 0f8eed33a3..c2121cb2e3 100644
--- a/src/core/hle/service/ir/ir.cpp
+++ b/src/core/hle/service/ir/ir.cpp
@@ -2,20 +2,22 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/shared_memory.h"
+
 #include "core/hle/service/service.h"
 #include "core/hle/service/ir/ir.h"
 #include "core/hle/service/ir/ir_rst.h"
 #include "core/hle/service/ir/ir_u.h"
 #include "core/hle/service/ir/ir_user.h"
 
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-
 namespace Service {
 namespace IR {
 
 static Kernel::SharedPtr<Kernel::Event> handle_event;
+static Kernel::SharedPtr<Kernel::Event> conn_status_event;
 static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
+static Kernel::SharedPtr<Kernel::SharedMemory> transfer_shared_memory;
 
 void GetHandles(Service::Interface* self) {
     u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -26,6 +28,64 @@ void GetHandles(Service::Interface* self) {
     cmd_buff[4] = Kernel::g_handle_table.Create(Service::IR::handle_event).MoveFrom();
 }
 
+void InitializeIrNopShared(Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    u32 transfer_buff_size = cmd_buff[1];
+    u32 recv_buff_size     = cmd_buff[2];
+    u32 unk1               = cmd_buff[3];
+    u32 send_buff_size     = cmd_buff[4];
+    u32 unk2               = cmd_buff[5];
+    u8  baud_rate          = cmd_buff[6] & 0xFF;
+    Handle handle          = cmd_buff[8];
+
+    if(Kernel::g_handle_table.IsValid(handle)) {
+        transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle);
+        transfer_shared_memory->name = "IR:TransferSharedMemory";
+    }
+
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+
+    LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, "
+                "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X",
+                transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle);
+}
+
+void RequireConnection(Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    conn_status_event->Signal();
+
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+
+    LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
+void Disconnect(Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+
+    LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
+void GetConnectionStatusEvent(Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+    cmd_buff[3] = Kernel::g_handle_table.Create(Service::IR::conn_status_event).MoveFrom();
+
+    LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
+void FinalizeIrNop(Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    cmd_buff[1] = RESULT_SUCCESS.raw;
+
+    LOG_WARNING(Service_IR, "(STUBBED) called");
+}
+
 void Init() {
     using namespace Kernel;
 
@@ -35,15 +95,19 @@ void Init() {
 
     using Kernel::MemoryPermission;
     shared_memory = SharedMemory::Create(0x1000, Kernel::MemoryPermission::ReadWrite,
-            Kernel::MemoryPermission::ReadWrite, "IR:SharedMemory");
+                                         Kernel::MemoryPermission::ReadWrite, "IR:SharedMemory");
+    transfer_shared_memory = nullptr;
 
     // Create event handle(s)
     handle_event  = Event::Create(RESETTYPE_ONESHOT, "IR:HandleEvent");
+    conn_status_event = Event::Create(RESETTYPE_ONESHOT, "IR:ConnectionStatusEvent");
 }
 
 void Shutdown() {
+    transfer_shared_memory = nullptr;
     shared_memory = nullptr;
     handle_event = nullptr;
+    conn_status_event = nullptr;
 }
 
 } // namespace IR
diff --git a/src/core/hle/service/ir/ir.h b/src/core/hle/service/ir/ir.h
index 3e107a8fe3..72d44ce605 100644
--- a/src/core/hle/service/ir/ir.h
+++ b/src/core/hle/service/ir/ir.h
@@ -20,6 +20,53 @@ namespace IR {
  */
 void GetHandles(Interface* self);
 
+/**
+ * IR::InitializeIrNopShared service function
+ *  Inputs:
+ *      1 : Size of transfer buffer
+ *      2 : Recv buffer size
+ *      3 : unknown
+ *      4 : Send buffer size
+ *      5 : unknown
+ *      6 : BaudRate (u8)
+ *      7 : 0
+ *      8 : Handle of transfer shared memory
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+void InitializeIrNopShared(Interface* self);
+
+/**
+ * IR::FinalizeIrNop service function
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+void FinalizeIrNop(Interface* self);
+
+/**
+ * IR::GetConnectionStatusEvent service function
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ *      2 : Connection Status Event handle
+ */
+void GetConnectionStatusEvent(Interface* self);
+
+/**
+ * IR::Disconnect service function
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+void Disconnect(Interface* self);
+
+/**
+ * IR::RequireConnection service function
+ *  Inputs:
+ *      1 : unknown (u8), looks like always 1
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+void RequireConnection(Interface* self);
+
 /// Initialize IR service
 void Init();
 
diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp
index 0a98e58014..06a6010294 100644
--- a/src/core/hle/service/ir/ir_user.cpp
+++ b/src/core/hle/service/ir/ir_user.cpp
@@ -2,26 +2,39 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include "core/hle/service/ir/ir.h"
 #include "core/hle/service/ir/ir_user.h"
 
 namespace Service {
 namespace IR {
 
 const Interface::FunctionInfo FunctionTable[] = {
-    {0x00010182, nullptr,                 "InitializeIrNop"},
-    {0x00020000, nullptr,                 "FinalizeIrNop"},
-    {0x00030000, nullptr,                 "ClearReceiveBuffer"},
-    {0x00040000, nullptr,                 "ClearSendBuffer"},
-    {0x00060040, nullptr,                 "RequireConnection"},
-    {0x00090000, nullptr,                 "Disconnect"},
-    {0x000A0000, nullptr,                 "GetReceiveEvent"},
-    {0x000B0000, nullptr,                 "GetSendEvent"},
-    {0x000C0000, nullptr,                 "GetConnectionStatusEvent"},
-    {0x000D0042, nullptr,                 "SendIrNop"},
-    {0x000E0042, nullptr,                 "SendIrNopLarge"},
-    {0x00180182, nullptr,                 "InitializeIrNopShared"},
-    {0x00190040, nullptr,                 "ReleaseReceivedData"},
-    {0x001A0040, nullptr,                 "SetOwnMachineId"},
+    {0x00010182, nullptr,                  "InitializeIrNop"},
+    {0x00020000, FinalizeIrNop,            "FinalizeIrNop"},
+    {0x00030000, nullptr,                  "ClearReceiveBuffer"},
+    {0x00040000, nullptr,                  "ClearSendBuffer"},
+    {0x000500C0, nullptr,                  "WaitConnection"},
+    {0x00060040, RequireConnection,        "RequireConnection"},
+    {0x000702C0, nullptr,                  "AutoConnection"},
+    {0x00080000, nullptr,                  "AnyConnection"},
+    {0x00090000, Disconnect,               "Disconnect"},
+    {0x000A0000, nullptr,                  "GetReceiveEvent"},
+    {0x000B0000, nullptr,                  "GetSendEvent"},
+    {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"},
+    {0x000D0042, nullptr,                  "SendIrNop"},
+    {0x000E0042, nullptr,                  "SendIrNopLarge"},
+    {0x000F0040, nullptr,                  "ReceiveIrnop"},
+    {0x00100042, nullptr,                  "ReceiveIrnopLarge"},
+    {0x00110040, nullptr,                  "GetLatestReceiveErrorResult"},
+    {0x00120040, nullptr,                  "GetLatestSendErrorResult"},
+    {0x00130000, nullptr,                  "GetConnectionStatus"},
+    {0x00140000, nullptr,                  "GetTryingToConnectStatus"},
+    {0x00150000, nullptr,                  "GetReceiveSizeFreeAndUsed"},
+    {0x00160000, nullptr,                  "GetSendSizeFreeAndUsed"},
+    {0x00170000, nullptr,                  "GetConnectionRole"},
+    {0x00180182, InitializeIrNopShared,    "InitializeIrNopShared"},
+    {0x00190040, nullptr,                  "ReleaseReceivedData"},
+    {0x001A0040, nullptr,                  "SetOwnMachineId"},
 };
 
 IR_User_Interface::IR_User_Interface() {