From c5a0408ccca4af6dc27e627a077d5480a3784e84 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 15 Jan 2018 17:19:32 -0500
Subject: [PATCH] Services: Stubbed APM::OpenSession and the ISession
 interface.

# Conflicts:
#	src/core/hle/service/am/applet_oe.cpp
#	src/core/hle/service/apm/apm.cpp
---
 src/core/hle/service/am/applet_oe.cpp |  3 +-
 src/core/hle/service/apm/apm.cpp      | 44 ++++++++++++++++++++++++++-
 src/core/hle/service/apm/apm.h        |  8 +++++
 3 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index ff0390b58a..03d9991b9c 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -6,6 +6,7 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/event.h"
 #include "core/hle/service/am/applet_oe.h"
+#include "core/hle/service/apm/apm.h"
 
 namespace Service {
 namespace AM {
@@ -184,7 +185,7 @@ private:
     void GetOperationMode(Kernel::HLERequestContext& ctx) {
         IPC::RequestBuilder rb{ctx, 3};
         rb.Push(RESULT_SUCCESS);
-        rb.Push(static_cast<u8>(OperationMode::Handheld));
+        rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld));
 
         LOG_WARNING(Service, "(STUBBED) called");
     }
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index 957abdd665..66d94ff525 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -13,12 +13,54 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
     std::make_shared<APM>()->InstallAsService(service_manager);
 }
 
+class ISession final : public ServiceFramework<ISession> {
+public:
+    ISession() : ServiceFramework("ISession") {
+        static const FunctionInfo functions[] = {
+            {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"},
+            {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+
+        auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
+        u32 config = rp.Pop<u32>();
+
+        IPC::RequestBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+
+        LOG_WARNING(Service, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode), config);
+    }
+
+    void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+
+        auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
+
+        IPC::RequestBuilder rb{ctx, 3};
+        rb.Push(RESULT_SUCCESS);
+        rb.Push<u32>(0); // Performance configuration
+
+        LOG_WARNING(Service, "(STUBBED) called mode=%u", static_cast<u32>(mode));
+    }
+};
+
 APM::APM() : ServiceFramework("apm") {
     static const FunctionInfo functions[] = {
-        {0x00000000, nullptr, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"},
+        {0x00000000, &APM::OpenSession, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"},
     };
     RegisterHandlers(functions);
 }
 
+void APM::OpenSession(Kernel::HLERequestContext& ctx) {
+    IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushIpcInterface<ISession>();
+}
+
 } // namespace APM
 } // namespace Service
diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h
index 377db71a4b..90a1afbbcb 100644
--- a/src/core/hle/service/apm/apm.h
+++ b/src/core/hle/service/apm/apm.h
@@ -9,10 +9,18 @@
 namespace Service {
 namespace APM {
 
+enum class PerformanceMode : u8 {
+    Handheld = 0,
+    Docked = 1,
+};
+
 class APM final : public ServiceFramework<APM> {
 public:
     APM();
     ~APM() = default;
+
+private:
+    void OpenSession(Kernel::HLERequestContext& ctx);
 };
 
 /// Registers all AM services with the specified service manager.