Compare commits
86 Commits
android-21
...
android-22
Author | SHA1 | Date | |
---|---|---|---|
fbf15f5058 | |||
f10157485d | |||
89f733a518 | |||
95802bc5b5 | |||
680fcdac60 | |||
386325553b | |||
c98d0e185f | |||
7cc7d027f7 | |||
12e5293c73 | |||
22492b68b7 | |||
a12a26e19b | |||
2a2a1d98b3 | |||
6e92a7a149 | |||
4dfe9dd038 | |||
d57165df45 | |||
738e9a79a0 | |||
aaab11e36f | |||
8f848f43e9 | |||
a7c1306e2d | |||
e8be665f11 | |||
9ed82a280e | |||
817d916233 | |||
ffe3984353 | |||
ec734cb06c | |||
8292ba7ad6 | |||
2e65616761 | |||
07aa1a99fa | |||
6524f20de4 | |||
a0f7f2b309 | |||
5510b31972 | |||
ecea5ef757 | |||
a1ce45b0b1 | |||
9ba9780a96 | |||
73e7a259fd | |||
8e0a40434c | |||
68303ed601 | |||
8a146469c0 | |||
b1c2f791af | |||
182137a9a4 | |||
3155f4e96d | |||
dfb9fa0144 | |||
a7e9d7842d | |||
7de6b41030 | |||
2cc5c517cf | |||
c0775e74ec | |||
3acf35bb98 | |||
8ddfecfbae | |||
51f5a6f1f8 | |||
64fca24b32 | |||
ba4cee1812 | |||
06abf3205a | |||
adfdc9520a | |||
90cb852908 | |||
278dd589ec | |||
15e8791f9d | |||
498c9bd96a | |||
6c8df6af44 | |||
8e93537266 | |||
b8f16f3538 | |||
6a2532fe17 | |||
3655115105 | |||
5561a08d59 | |||
e687ca8735 | |||
0bf46cb1ee | |||
19a2f12692 | |||
6cc82fd430 | |||
72c897c49d | |||
077a50a547 | |||
820f1c8a16 | |||
b163757e1f | |||
2bc0132d0c | |||
b75401a2cb | |||
12e7ee2357 | |||
3ec41503e3 | |||
c770af9b12 | |||
2d8f80b65e | |||
6c4eb2733d | |||
5a20d07c21 | |||
9f91d310c6 | |||
6527c0d2fc | |||
da410506a4 | |||
c5e88c654e | |||
23e074ff14 | |||
f854ffd015 | |||
e231b8b6f5 | |||
68fe1e3476 |
4
.github/workflows/verify.yml
vendored
4
.github/workflows/verify.yml
vendored
@ -73,7 +73,7 @@ jobs:
|
||||
build-mac:
|
||||
name: 'test build (macos)'
|
||||
needs: format
|
||||
runs-on: macos-13
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@ -87,7 +87,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
export Qt5_DIR="/usr/local/opt/qt@5/lib/cmake"
|
||||
export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake"
|
||||
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
|
||||
ninja
|
||||
build-msvc:
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -64,3 +64,6 @@
|
||||
[submodule "oaknut"]
|
||||
path = externals/oaknut
|
||||
url = https://github.com/merryhime/oaknut
|
||||
[submodule "Vulkan-Utility-Libraries"]
|
||||
path = externals/Vulkan-Utility-Libraries
|
||||
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
|
||||
|
@ -36,6 +36,8 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
|
||||
|
||||
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
||||
|
||||
option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
|
||||
|
||||
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
|
||||
|
||||
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
||||
@ -308,6 +310,10 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||
find_package(Vulkan 1.3.274 REQUIRED)
|
||||
endif()
|
||||
|
||||
if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
||||
find_package(VulkanUtilityLibraries REQUIRED)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LIBUSB)
|
||||
find_package(libusb 1.0.24 MODULE)
|
||||
endif()
|
||||
@ -316,6 +322,10 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
find_package(xbyak 6 CONFIG)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_arm64)
|
||||
find_package(oaknut 2.0.1 CONFIG)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
find_package(dynarmic 6.4.0 CONFIG)
|
||||
endif()
|
||||
|
10
README.md
10
README.md
@ -1,10 +1,10 @@
|
||||
| Pull Request | Commit | Title | Author | Merged? |
|
||||
|----|----|----|----|----|
|
||||
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`53f17ede1`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12802](https://github.com/yuzu-emu/yuzu-android//pull/12802) | [`c5e88c654`](https://github.com/yuzu-emu/yuzu-android//pull/12802/files) | service: mii: Migrate service to new interface | [german77](https://github.com/german77/) | Yes |
|
||||
| [12826](https://github.com/yuzu-emu/yuzu-android//pull/12826) | [`2d8f80b65`](https://github.com/yuzu-emu/yuzu-android//pull/12826/files) | android: Show system driver information | [t895](https://github.com/t895/) | Yes |
|
||||
| [12827](https://github.com/yuzu-emu/yuzu-android//pull/12827) | [`c770af9b1`](https://github.com/yuzu-emu/yuzu-android//pull/12827/files) | android: Disable focus on loading card | [t895](https://github.com/t895/) | Yes |
|
||||
| [12461](https://github.com/yuzu-emu/yuzu-android//pull/12461) | [`e1f31cfe5`](https://github.com/yuzu-emu/yuzu-android//pull/12461/files) | Rework Nvdec and VIC to fix out-of-order videos, and speed up decoding. | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
||||
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`aad4b0d6f`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12848](https://github.com/yuzu-emu/yuzu-android//pull/12848) | [`4afca6bf5`](https://github.com/yuzu-emu/yuzu-android//pull/12848/files) | service: capsrv: Migrate to new IPC | [german77](https://github.com/german77/) | Yes |
|
||||
| [12874](https://github.com/yuzu-emu/yuzu-android//pull/12874) | [`f410cf681`](https://github.com/yuzu-emu/yuzu-android//pull/12874/files) | Revert "shader_recompiler: fix Offset operand usage for non-OpImage*Gather" | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12875](https://github.com/yuzu-emu/yuzu-android//pull/12875) | [`5cb9fe781`](https://github.com/yuzu-emu/yuzu-android//pull/12875/files) | SwBlitter: Fix Pitch linear reading/writting | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
||||
|
||||
|
||||
End of merge log. You can find the original README.md below the break.
|
||||
|
10
externals/CMakeLists.txt
vendored
10
externals/CMakeLists.txt
vendored
@ -14,16 +14,17 @@ set(BUILD_SHARED_LIBS OFF)
|
||||
# Skip install rules for all externals
|
||||
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
|
||||
# xbyak
|
||||
# Xbyak (also used by Dynarmic, so needs to be added first)
|
||||
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
||||
add_subdirectory(xbyak)
|
||||
endif()
|
||||
|
||||
# Dynarmic
|
||||
# Oaknut (also used by Dynarmic, so needs to be added first)
|
||||
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
|
||||
add_subdirectory(oaknut)
|
||||
endif()
|
||||
|
||||
# Dynarmic
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
||||
set(DYNARMIC_IGNORE_ASSERTS ON)
|
||||
add_subdirectory(dynarmic)
|
||||
@ -154,6 +155,11 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||
add_subdirectory(Vulkan-Headers)
|
||||
endif()
|
||||
|
||||
# Vulkan-Utility-Libraries
|
||||
if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
||||
add_subdirectory(Vulkan-Utility-Libraries)
|
||||
endif()
|
||||
|
||||
# TZDB (Time Zone Database)
|
||||
add_subdirectory(nx_tzdb)
|
||||
|
||||
|
1
externals/Vulkan-Utility-Libraries
vendored
Submodule
1
externals/Vulkan-Utility-Libraries
vendored
Submodule
Submodule externals/Vulkan-Utility-Libraries added at 524f8910d0
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 0df09e2f6b...ca0e264f4f
2
externals/oaknut
vendored
2
externals/oaknut
vendored
Submodule externals/oaknut updated: 918bd94f02...9d091109de
4
externals/tz/tz/tz.cpp
vendored
4
externals/tz/tz/tz.cpp
vendored
@ -1625,11 +1625,11 @@ s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep) {
|
||||
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep) {
|
||||
return localsub(sp, timep, 0, tmp) == nullptr;
|
||||
}
|
||||
|
||||
u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp) {
|
||||
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp) {
|
||||
return time1(out_time, tmp, localsub, sp, 0);
|
||||
}
|
||||
|
||||
|
4
externals/tz/tz/tz.h
vendored
4
externals/tz/tz/tz.h
vendored
@ -75,7 +75,7 @@ static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has th
|
||||
|
||||
s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary);
|
||||
|
||||
bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep);
|
||||
u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp);
|
||||
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep);
|
||||
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp);
|
||||
|
||||
} // namespace Tz
|
||||
|
@ -261,7 +261,7 @@ object NativeLibrary {
|
||||
/**
|
||||
* Begins emulation.
|
||||
*/
|
||||
external fun run(path: String?, programIndex: Int = 0)
|
||||
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
|
||||
|
||||
// Surface Handling
|
||||
external fun surfaceChanged(surf: Surface?)
|
||||
|
@ -7,6 +7,7 @@ import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
import org.yuzu.yuzu_emu.model.Driver
|
||||
@ -57,13 +58,9 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) :
|
||||
title.text = model.title
|
||||
version.text = model.version
|
||||
description.text = model.description
|
||||
if (model.description.isNotEmpty()) {
|
||||
version.visibility = View.VISIBLE
|
||||
description.visibility = View.VISIBLE
|
||||
if (model.title != binding.root.context.getString(R.string.system_gpu_driver)) {
|
||||
buttonDelete.visibility = View.VISIBLE
|
||||
} else {
|
||||
version.visibility = View.GONE
|
||||
description.visibility = View.GONE
|
||||
buttonDelete.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
emulationThread.join()
|
||||
emulationThread = Thread({
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||
NativeLibrary.run(gamePath, programIndex)
|
||||
NativeLibrary.run(gamePath, programIndex, false)
|
||||
}, "NativeEmulation")
|
||||
emulationThread.start()
|
||||
}
|
||||
@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
State.STOPPED -> {
|
||||
emulationThread = Thread({
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||
NativeLibrary.run(gamePath, programIndex)
|
||||
NativeLibrary.run(gamePath, programIndex, true)
|
||||
}, "NativeEmulation")
|
||||
emulationThread.start()
|
||||
}
|
||||
|
@ -219,7 +219,8 @@ void EmulationSession::SetAppletId(int applet_id) {
|
||||
}
|
||||
|
||||
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
||||
const std::size_t program_index) {
|
||||
const std::size_t program_index,
|
||||
const bool frontend_initiated) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
|
||||
// Create the render window.
|
||||
@ -251,6 +252,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
||||
// Load the ROM.
|
||||
Service::AM::FrontendAppletParameters params{
|
||||
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
||||
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
|
||||
: Service::AM::LaunchType::ApplicationInitiated,
|
||||
.program_index = static_cast<s32>(program_index),
|
||||
};
|
||||
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
||||
@ -447,7 +450,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
||||
}
|
||||
|
||||
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||
const size_t program_index = 0) {
|
||||
const size_t program_index,
|
||||
const bool frontend_initiated) {
|
||||
MicroProfileOnThreadCreate("EmuThread");
|
||||
SCOPE_EXIT({ MicroProfileShutdown(); });
|
||||
|
||||
@ -460,7 +464,8 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||
|
||||
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
||||
|
||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
|
||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
|
||||
frontend_initiated);
|
||||
if (result != Core::SystemResultStatus::Success) {
|
||||
return result;
|
||||
}
|
||||
@ -757,10 +762,12 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
||||
jint j_program_index) {
|
||||
jint j_program_index,
|
||||
jboolean j_frontend_initiated) {
|
||||
const std::string path = GetJString(env, j_path);
|
||||
|
||||
const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
|
||||
const Core::SystemResultStatus result{
|
||||
RunEmulation(path, j_program_index, j_frontend_initiated)};
|
||||
if (result != Core::SystemResultStatus::Success) {
|
||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
||||
|
@ -47,7 +47,8 @@ public:
|
||||
void InitializeSystem(bool reload);
|
||||
void SetAppletId(int applet_id);
|
||||
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
||||
const std::size_t program_index = 0);
|
||||
const std::size_t program_index,
|
||||
const bool frontend_initiated);
|
||||
|
||||
bool IsHandheldOnly();
|
||||
void SetDeviceType([[maybe_unused]] int index, int type);
|
||||
|
@ -210,8 +210,6 @@ add_library(audio_core STATIC
|
||||
sink/sink_stream.h
|
||||
)
|
||||
|
||||
create_target_directory_groups(audio_core)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(audio_core PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
@ -267,3 +265,5 @@ endif()
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(audio_core)
|
||||
|
@ -89,11 +89,13 @@ u32 AudioRenderer::Receive(Direction dir) {
|
||||
}
|
||||
|
||||
void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
|
||||
u64 applet_resource_user_id, bool reset) noexcept {
|
||||
u64 applet_resource_user_id, Kernel::KProcess* process,
|
||||
bool reset) noexcept {
|
||||
command_buffers[session_id].buffer = buffer;
|
||||
command_buffers[session_id].size = size;
|
||||
command_buffers[session_id].time_limit = time_limit;
|
||||
command_buffers[session_id].applet_resource_user_id = applet_resource_user_id;
|
||||
command_buffers[session_id].process = process;
|
||||
command_buffers[session_id].reset_buffer = reset;
|
||||
}
|
||||
|
||||
@ -173,7 +175,8 @@ void AudioRenderer::Main(std::stop_token stop_token) {
|
||||
// If there are no remaining commands (from the previous list),
|
||||
// this is a new command list, initialize it.
|
||||
if (command_buffer.remaining_command_count == 0) {
|
||||
command_list_processor.Initialize(system, command_buffer.buffer,
|
||||
command_list_processor.Initialize(system, *command_buffer.process,
|
||||
command_buffer.buffer,
|
||||
command_buffer.size, streams[index]);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,10 @@ namespace Core {
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
namespace Kernel {
|
||||
class KProcess;
|
||||
}
|
||||
|
||||
namespace AudioCore {
|
||||
namespace Sink {
|
||||
class Sink;
|
||||
@ -69,7 +73,8 @@ public:
|
||||
u32 Receive(Direction dir);
|
||||
|
||||
void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
|
||||
u64 applet_resource_user_id, bool reset) noexcept;
|
||||
u64 applet_resource_user_id, Kernel::KProcess* process,
|
||||
bool reset) noexcept;
|
||||
u32 GetRemainCommandCount(s32 session_id) const noexcept;
|
||||
void ClearRemainCommandCount(s32 session_id) noexcept;
|
||||
u64 GetRenderingStartTick(s32 session_id) const noexcept;
|
||||
|
@ -6,6 +6,10 @@
|
||||
#include "audio_core/common/common.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Kernel {
|
||||
class KProcess;
|
||||
}
|
||||
|
||||
namespace AudioCore::ADSP::AudioRenderer {
|
||||
|
||||
struct CommandBuffer {
|
||||
@ -14,6 +18,7 @@ struct CommandBuffer {
|
||||
u64 size{};
|
||||
u64 time_limit{};
|
||||
u64 applet_resource_user_id{};
|
||||
Kernel::KProcess* process{};
|
||||
bool reset_buffer{};
|
||||
// Set by the DSP
|
||||
u32 remaining_command_count{};
|
||||
|
@ -9,14 +9,15 @@
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace AudioCore::ADSP::AudioRenderer {
|
||||
|
||||
void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
|
||||
Sink::SinkStream* stream_) {
|
||||
void CommandListProcessor::Initialize(Core::System& system_, Kernel::KProcess& process,
|
||||
CpuAddr buffer, u64 size, Sink::SinkStream* stream_) {
|
||||
system = &system_;
|
||||
memory = &system->ApplicationMemory();
|
||||
memory = &process.GetMemory();
|
||||
stream = stream_;
|
||||
header = reinterpret_cast<Renderer::CommandListHeader*>(buffer);
|
||||
commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));
|
||||
|
@ -16,6 +16,10 @@ class Memory;
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
namespace Kernel {
|
||||
class KProcess;
|
||||
}
|
||||
|
||||
namespace AudioCore {
|
||||
namespace Sink {
|
||||
class SinkStream;
|
||||
@ -40,7 +44,8 @@ public:
|
||||
* @param size - The size of the buffer.
|
||||
* @param stream - The stream to be used for sending the samples.
|
||||
*/
|
||||
void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream);
|
||||
void Initialize(Core::System& system, Kernel::KProcess& process, CpuAddr buffer, u64 size,
|
||||
Sink::SinkStream* stream);
|
||||
|
||||
/**
|
||||
* Set the maximum processing time for this command list.
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "audio_core/renderer/audio_renderer.h"
|
||||
#include "audio_core/renderer/system_manager.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/service/audio/errors.h"
|
||||
|
||||
@ -17,7 +18,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
|
||||
Result Renderer::Initialize(const AudioRendererParameterInternal& params,
|
||||
Kernel::KTransferMemory* transfer_memory,
|
||||
const u64 transfer_memory_size, const u32 process_handle,
|
||||
const u64 applet_resource_user_id, const s32 session_id) {
|
||||
Kernel::KProcess& process, const u64 applet_resource_user_id,
|
||||
const s32 session_id) {
|
||||
if (params.execution_mode == ExecutionMode::Auto) {
|
||||
if (!manager.AddSystem(system)) {
|
||||
LOG_ERROR(Service_Audio,
|
||||
@ -28,7 +30,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
|
||||
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
|
||||
applet_resource_user_id, session_id);
|
||||
|
||||
return ResultSuccess;
|
||||
|
@ -14,7 +14,8 @@ class System;
|
||||
|
||||
namespace Kernel {
|
||||
class KTransferMemory;
|
||||
}
|
||||
class KProcess;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace AudioCore {
|
||||
struct AudioRendererParameterInternal;
|
||||
@ -44,7 +45,8 @@ public:
|
||||
*/
|
||||
Result Initialize(const AudioRendererParameterInternal& params,
|
||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
||||
u32 process_handle, u64 applet_resource_user_id, s32 session_id);
|
||||
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
|
||||
s32 session_id);
|
||||
|
||||
/**
|
||||
* Finalize the renderer for shutdown.
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
@ -101,7 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
|
||||
|
||||
Result System::Initialize(const AudioRendererParameterInternal& params,
|
||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
||||
u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) {
|
||||
u32 process_handle_, Kernel::KProcess& process_,
|
||||
u64 applet_resource_user_id_, s32 session_id_) {
|
||||
if (!CheckValidRevision(params.revision)) {
|
||||
return Service::Audio::ResultInvalidRevision;
|
||||
}
|
||||
@ -117,6 +119,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
|
||||
behavior.SetUserLibRevision(params.revision);
|
||||
|
||||
process_handle = process_handle_;
|
||||
process = &process_;
|
||||
applet_resource_user_id = applet_resource_user_id_;
|
||||
session_id = session_id_;
|
||||
|
||||
@ -129,7 +132,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
|
||||
render_device = params.rendering_device;
|
||||
execution_mode = params.execution_mode;
|
||||
|
||||
core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
|
||||
process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
|
||||
|
||||
// Note: We're not actually using the transfer memory because it's a pain to code for.
|
||||
// Allocate the memory normally instead and hope the game doesn't try to read anything back
|
||||
@ -613,7 +616,8 @@ void System::SendCommandToDsp() {
|
||||
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
|
||||
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
|
||||
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
|
||||
applet_resource_user_id, reset_command_buffers);
|
||||
applet_resource_user_id, process,
|
||||
reset_command_buffers);
|
||||
reset_command_buffers = false;
|
||||
command_buffer_size = command_size;
|
||||
if (remaining_command_count == 0) {
|
||||
|
@ -29,6 +29,7 @@ class System;
|
||||
|
||||
namespace Kernel {
|
||||
class KEvent;
|
||||
class KProcess;
|
||||
class KTransferMemory;
|
||||
} // namespace Kernel
|
||||
|
||||
@ -80,7 +81,8 @@ public:
|
||||
*/
|
||||
Result Initialize(const AudioRendererParameterInternal& params,
|
||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
||||
u32 process_handle, u64 applet_resource_user_id, s32 session_id);
|
||||
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
|
||||
s32 session_id);
|
||||
|
||||
/**
|
||||
* Finalize the system.
|
||||
@ -275,6 +277,8 @@ private:
|
||||
Common::Event terminate_event{};
|
||||
/// Does what locks do
|
||||
std::mutex lock{};
|
||||
/// Process this audio render is operating within, used for memory reads/writes.
|
||||
Kernel::KProcess* process{};
|
||||
/// Handle for the process for this system, unused
|
||||
u32 process_handle{};
|
||||
/// Applet resource id for this system, unused
|
||||
|
@ -245,8 +245,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(common)
|
||||
|
||||
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
|
||||
|
||||
@ -258,3 +256,5 @@ endif()
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers(common PRIVATE precompiled_headers.h)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(common)
|
||||
|
@ -15,25 +15,34 @@ namespace Common {
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected);
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual);
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected) {
|
||||
const u8 result =
|
||||
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
|
||||
return result == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected) {
|
||||
const u16 result =
|
||||
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
|
||||
return result == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected) {
|
||||
const u32 result =
|
||||
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
|
||||
return result == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected) {
|
||||
const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer),
|
||||
value, expected);
|
||||
return result == expected;
|
||||
@ -45,29 +54,32 @@ namespace Common {
|
||||
reinterpret_cast<__int64*>(expected.data())) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
|
||||
u8& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected, u8& actual) {
|
||||
actual =
|
||||
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
|
||||
u16& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected,
|
||||
u16& actual) {
|
||||
actual =
|
||||
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
|
||||
u32& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected,
|
||||
u32& actual) {
|
||||
actual =
|
||||
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
|
||||
u64& actual) {
|
||||
template <>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected,
|
||||
u64& actual) {
|
||||
actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value,
|
||||
expected);
|
||||
return actual == expected;
|
||||
@ -91,23 +103,12 @@ namespace Common {
|
||||
|
||||
#else
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
|
||||
return __sync_bool_compare_and_swap(pointer, expected, value);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) {
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected) {
|
||||
unsigned __int128 value_a;
|
||||
unsigned __int128 expected_a;
|
||||
std::memcpy(&value_a, value.data(), sizeof(u128));
|
||||
@ -115,31 +116,13 @@ namespace Common {
|
||||
return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
|
||||
u8& actual) {
|
||||
template <typename T>
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
|
||||
u16& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
|
||||
u32& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
|
||||
u64& actual) {
|
||||
actual = __sync_val_compare_and_swap(pointer, expected, value);
|
||||
return actual == expected;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected,
|
||||
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected,
|
||||
u128& actual) {
|
||||
unsigned __int128 value_a;
|
||||
unsigned __int128 expected_a;
|
||||
@ -151,7 +134,7 @@ namespace Common {
|
||||
return actual_a == expected_a;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) {
|
||||
[[nodiscard]] inline u128 AtomicLoad128(u64* pointer) {
|
||||
unsigned __int128 zeros_a = 0;
|
||||
unsigned __int128 result_a =
|
||||
__sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);
|
||||
|
@ -134,12 +134,12 @@ struct Values {
|
||||
Linkage linkage{};
|
||||
|
||||
// Audio
|
||||
Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
|
||||
Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<std::string> audio_output_device_id{
|
||||
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<std::string> audio_input_device_id{
|
||||
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<AudioMode, true> sound_index{
|
||||
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
||||
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
||||
|
@ -979,8 +979,6 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(core)
|
||||
|
||||
target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz)
|
||||
target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API)
|
||||
if (MINGW)
|
||||
@ -1058,3 +1056,5 @@ endif()
|
||||
if (YUZU_ENABLE_LTO)
|
||||
set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(core)
|
||||
|
@ -201,22 +201,22 @@ struct System::Impl {
|
||||
system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock;
|
||||
static_service_a->GetStandardUserSystemClock(user_clock);
|
||||
static_service_a->GetStandardUserSystemClock(&user_clock);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
|
||||
static_service_a->GetStandardLocalSystemClock(local_clock);
|
||||
static_service_a->GetStandardLocalSystemClock(&local_clock);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> network_clock;
|
||||
static_service_s->GetStandardNetworkSystemClock(network_clock);
|
||||
static_service_s->GetStandardNetworkSystemClock(&network_clock);
|
||||
|
||||
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service;
|
||||
static_service_a->GetTimeZoneService(timezone_service);
|
||||
static_service_a->GetTimeZoneService(&timezone_service);
|
||||
|
||||
Service::PSC::Time::LocationName name{};
|
||||
auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
|
||||
std::memcpy(name.name.data(), new_name.data(), std::min(name.name.size(), new_name.size()));
|
||||
std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size()));
|
||||
|
||||
timezone_service->SetDeviceLocation(name);
|
||||
timezone_service->SetDeviceLocationName(name);
|
||||
|
||||
u64 time_offset = 0;
|
||||
if (Settings::values.custom_rtc_enabled) {
|
||||
@ -234,7 +234,7 @@ struct System::Impl {
|
||||
|
||||
local_clock->SetCurrentTime(new_time);
|
||||
|
||||
network_clock->GetSystemClockContext(context);
|
||||
network_clock->GetSystemClockContext(&context);
|
||||
settings_service->SetNetworkSystemClockContext(context);
|
||||
network_clock->SetCurrentTime(new_time);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@ -42,6 +43,8 @@ public:
|
||||
DeviceMemoryManager(const DeviceMemory& device_memory);
|
||||
~DeviceMemoryManager();
|
||||
|
||||
static constexpr bool HAS_FLUSH_INVALIDATION = true;
|
||||
|
||||
void BindInterface(DeviceInterface* device_inter);
|
||||
|
||||
DAddr Allocate(size_t size);
|
||||
@ -181,24 +184,28 @@ private:
|
||||
}
|
||||
|
||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||
static constexpr size_t subentries = 8 / sizeof(u8);
|
||||
using CounterType = u8;
|
||||
using CounterAtomicType = std::atomic_uint8_t;
|
||||
static constexpr size_t subentries = 8 / sizeof(CounterType);
|
||||
static constexpr size_t subentries_mask = subentries - 1;
|
||||
static constexpr size_t subentries_shift =
|
||||
std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType));
|
||||
class CounterEntry final {
|
||||
public:
|
||||
CounterEntry() = default;
|
||||
|
||||
std::atomic_uint8_t& Count(std::size_t page) {
|
||||
CounterAtomicType& Count(std::size_t page) {
|
||||
return values[page & subentries_mask];
|
||||
}
|
||||
|
||||
const std::atomic_uint8_t& Count(std::size_t page) const {
|
||||
const CounterAtomicType& Count(std::size_t page) const {
|
||||
return values[page & subentries_mask];
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<std::atomic_uint8_t, subentries> values{};
|
||||
std::array<CounterAtomicType, subentries> values{};
|
||||
};
|
||||
static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
|
||||
static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType),
|
||||
"CounterEntry should be 8 bytes!");
|
||||
|
||||
static constexpr size_t num_counter_entries =
|
||||
|
@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
|
||||
Asid asid, bool track) {
|
||||
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid,
|
||||
bool track) {
|
||||
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||
@ -519,22 +519,36 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
|
||||
size_t page = addr >> Memory::YUZU_PAGEBITS;
|
||||
auto [asid, base_vaddress] = ExtractCPUBacking(page);
|
||||
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
|
||||
auto* memory_device_inter = registered_processes[asid.id];
|
||||
const auto release_pending = [&] {
|
||||
if (uncache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
|
||||
uncache_bytes, false);
|
||||
uncache_bytes = 0;
|
||||
}
|
||||
if (cache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
|
||||
cache_bytes, true);
|
||||
cache_bytes = 0;
|
||||
}
|
||||
};
|
||||
for (; page != page_end; ++page) {
|
||||
std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
|
||||
CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page);
|
||||
auto [asid_2, vpage] = ExtractCPUBacking(page);
|
||||
vpage >>= Memory::YUZU_PAGEBITS;
|
||||
|
||||
if (delta > 0) {
|
||||
ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
|
||||
"Count may overflow!");
|
||||
} else if (delta < 0) {
|
||||
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
|
||||
} else {
|
||||
ASSERT_MSG(false, "Delta must be non-zero!");
|
||||
if (vpage == 0) [[unlikely]] {
|
||||
release_pending();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (asid.id != asid_2.id) [[unlikely]] {
|
||||
release_pending();
|
||||
memory_device_inter = registered_processes[asid_2.id];
|
||||
}
|
||||
|
||||
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
||||
count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
|
||||
count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release);
|
||||
|
||||
// Assume delta is either -1 or 1
|
||||
if (count.load(std::memory_order::relaxed) == 0) {
|
||||
@ -553,20 +567,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
}
|
||||
cache_bytes += Memory::YUZU_PAGESIZE;
|
||||
} else if (cache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||
true);
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
|
||||
cache_bytes, true);
|
||||
cache_bytes = 0;
|
||||
}
|
||||
vpage++;
|
||||
}
|
||||
if (uncache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
|
||||
false);
|
||||
}
|
||||
if (cache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||
true);
|
||||
}
|
||||
release_pending();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
@ -44,15 +44,32 @@ public:
|
||||
GuestMemory() = delete;
|
||||
explicit GuestMemory(M& memory, u64 addr, std::size_t size,
|
||||
Common::ScratchBuffer<T>* backup = nullptr)
|
||||
: m_memory{memory}, m_addr{addr}, m_size{size} {
|
||||
: m_memory{&memory}, m_addr{addr}, m_size{size} {
|
||||
static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Read) {
|
||||
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
|
||||
if (!this->TrySetSpan()) {
|
||||
if (backup) {
|
||||
backup->resize_destructive(this->size());
|
||||
m_data_span = *backup;
|
||||
m_span_valid = true;
|
||||
m_is_data_copy = true;
|
||||
} else {
|
||||
m_data_copy.resize(this->size());
|
||||
m_data_span = std::span(m_data_copy);
|
||||
m_span_valid = true;
|
||||
m_is_data_copy = true;
|
||||
}
|
||||
}
|
||||
} else if constexpr (FLAGS & GuestMemoryFlags::Read) {
|
||||
Read(addr, size, backup);
|
||||
}
|
||||
}
|
||||
|
||||
~GuestMemory() = default;
|
||||
|
||||
GuestMemory(GuestMemory&& rhs) = default;
|
||||
GuestMemory& operator=(GuestMemory&& rhs) = default;
|
||||
|
||||
T* data() noexcept {
|
||||
return m_data_span.data();
|
||||
}
|
||||
@ -109,8 +126,8 @@ public:
|
||||
}
|
||||
|
||||
if (this->TrySetSpan()) {
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||
m_memory.FlushRegion(m_addr, this->size_bytes());
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Safe && M::HAS_FLUSH_INVALIDATION) {
|
||||
m_memory->FlushRegion(m_addr, this->size_bytes());
|
||||
}
|
||||
} else {
|
||||
if (backup) {
|
||||
@ -123,9 +140,9 @@ public:
|
||||
m_is_data_copy = true;
|
||||
m_span_valid = true;
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||
m_memory.ReadBlock(m_addr, this->data(), this->size_bytes());
|
||||
m_memory->ReadBlock(m_addr, this->data(), this->size_bytes());
|
||||
} else {
|
||||
m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
|
||||
m_memory->ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
|
||||
}
|
||||
}
|
||||
return m_data_span;
|
||||
@ -133,18 +150,19 @@ public:
|
||||
|
||||
void Write(std::span<T> write_data) noexcept {
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||
m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
|
||||
m_memory->WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
|
||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||
m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes());
|
||||
m_memory->WriteBlock(m_addr, write_data.data(), this->size_bytes());
|
||||
} else {
|
||||
m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
|
||||
m_memory->WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
bool TrySetSpan() noexcept {
|
||||
if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) {
|
||||
if (u8* ptr = m_memory->GetSpan(m_addr, this->size_bytes()); ptr) {
|
||||
m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
|
||||
m_span_valid = true;
|
||||
m_is_data_copy = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -159,7 +177,7 @@ protected:
|
||||
return m_addr_changed;
|
||||
}
|
||||
|
||||
M& m_memory;
|
||||
M* m_memory;
|
||||
u64 m_addr{};
|
||||
size_t m_size{};
|
||||
std::span<T> m_data_span{};
|
||||
@ -175,17 +193,7 @@ public:
|
||||
GuestMemoryScoped() = delete;
|
||||
explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
|
||||
Common::ScratchBuffer<T>* backup = nullptr)
|
||||
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {
|
||||
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
|
||||
if (!this->TrySetSpan()) {
|
||||
if (backup) {
|
||||
this->m_data_span = *backup;
|
||||
this->m_span_valid = true;
|
||||
this->m_is_data_copy = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {}
|
||||
|
||||
~GuestMemoryScoped() {
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Write) {
|
||||
@ -196,15 +204,17 @@ public:
|
||||
if (this->AddressChanged() || this->IsDataCopy()) {
|
||||
ASSERT(this->m_span_valid);
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||
this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
|
||||
this->m_memory->WriteBlockCached(this->m_addr, this->data(),
|
||||
this->size_bytes());
|
||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||
this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes());
|
||||
this->m_memory->WriteBlock(this->m_addr, this->data(), this->size_bytes());
|
||||
} else {
|
||||
this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
|
||||
this->m_memory->WriteBlockUnsafe(this->m_addr, this->data(),
|
||||
this->size_bytes());
|
||||
}
|
||||
} else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
|
||||
(FLAGS & GuestMemoryFlags::Cached)) {
|
||||
this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes());
|
||||
this->m_memory->InvalidateRegion(this->m_addr, this->size_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -543,7 +543,8 @@ void KThread::Unpin() {
|
||||
ASSERT(m_parent != nullptr);
|
||||
|
||||
// Resume any threads that began waiting on us while we were pinned.
|
||||
for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) {
|
||||
for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end();
|
||||
it = m_pinned_waiter_list.erase(it)) {
|
||||
it->EndWait(ResultSuccess);
|
||||
}
|
||||
}
|
||||
|
@ -303,8 +303,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||
}
|
||||
|
||||
// Applet was started by frontend, so it is foreground.
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
applet->focus_state = FocusState::InFocus;
|
||||
|
||||
this->InsertApplet(std::move(applet));
|
||||
|
@ -207,7 +207,7 @@ void Error::Execute() {
|
||||
|
||||
void Error::DisplayCompleted() {
|
||||
complete = true;
|
||||
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>()));
|
||||
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||
Exit();
|
||||
}
|
||||
|
||||
|
@ -85,24 +85,26 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
|
||||
applet->library_applet_mode = mode;
|
||||
|
||||
// Set focus state
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
switch (mode) {
|
||||
case LibraryAppletMode::AllForeground:
|
||||
case LibraryAppletMode::NoUI:
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||
applet->focus_state = FocusState::InFocus;
|
||||
applet->hid_registration.EnableAppletToGetInput(true);
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
break;
|
||||
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
||||
applet->system_buffer_manager.SetWindowVisibility(false);
|
||||
applet->focus_state = FocusState::NotInFocus;
|
||||
applet->hid_registration.EnableAppletToGetInput(false);
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
break;
|
||||
case LibraryAppletMode::Background:
|
||||
case LibraryAppletMode::BackgroundIndirectDisplay:
|
||||
default:
|
||||
applet->focus_state = FocusState::Background;
|
||||
applet->hid_registration.EnableAppletToGetInput(true);
|
||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ void AOC_U::ListAddOnContent(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count,
|
||||
process_id);
|
||||
|
||||
const auto current = system.GetApplicationProcessProgramID();
|
||||
const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID());
|
||||
|
||||
std::vector<u32> out;
|
||||
const auto& disabled = Settings::values.disabled_addons[current];
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/service/audio/audctl.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/set/system_settings_server.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
@ -19,15 +21,15 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
||||
{6, nullptr, "IsTargetConnected"},
|
||||
{7, nullptr, "SetDefaultTarget"},
|
||||
{8, nullptr, "GetDefaultTarget"},
|
||||
{9, nullptr, "GetAudioOutputMode"},
|
||||
{10, nullptr, "SetAudioOutputMode"},
|
||||
{9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"},
|
||||
{10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"},
|
||||
{11, nullptr, "SetForceMutePolicy"},
|
||||
{12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
|
||||
{13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
|
||||
{14, nullptr, "SetOutputModeSetting"},
|
||||
{14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"},
|
||||
{15, nullptr, "SetOutputTarget"},
|
||||
{16, nullptr, "SetInputTargetForceEnabled"},
|
||||
{17, nullptr, "SetHeadphoneOutputLevelMode"},
|
||||
{17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"},
|
||||
{18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
|
||||
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
|
||||
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
|
||||
@ -40,7 +42,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
||||
{27, nullptr, "SetVolumeMappingTableForDev"},
|
||||
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||
{30, nullptr, "SetSpeakerAutoMuteEnabled"},
|
||||
{30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"},
|
||||
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
|
||||
{32, nullptr, "GetActiveOutputTarget"},
|
||||
{33, nullptr, "GetTargetDeviceInfo"},
|
||||
@ -68,6 +70,9 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
m_set_sys =
|
||||
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
||||
}
|
||||
|
||||
AudCtl::~AudCtl() = default;
|
||||
@ -96,6 +101,33 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
|
||||
rb.Push(target_max_volume);
|
||||
}
|
||||
|
||||
void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
|
||||
|
||||
Set::AudioOutputMode output_mode{};
|
||||
const auto result = m_set_sys->GetAudioOutputMode(output_mode, target);
|
||||
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(result);
|
||||
rb.PushEnum(output_mode);
|
||||
}
|
||||
|
||||
void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
|
||||
const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
|
||||
|
||||
const auto result = m_set_sys->SetAudioOutputMode(target, output_mode);
|
||||
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
}
|
||||
|
||||
void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Audio, "(STUBBED) called");
|
||||
|
||||
@ -106,13 +138,31 @@ void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
|
||||
|
||||
void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto value = rp.Pop<u32>();
|
||||
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
|
||||
|
||||
LOG_WARNING(Audio, "(STUBBED) called, value={}", value);
|
||||
LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(AudioOutputMode::PcmAuto);
|
||||
rb.PushEnum(Set::AudioOutputMode::ch_7_1);
|
||||
}
|
||||
|
||||
void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
|
||||
const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
|
||||
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Audio, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
|
||||
@ -123,14 +173,28 @@ void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
|
||||
rb.PushEnum(HeadphoneOutputLevelMode::Normal);
|
||||
}
|
||||
|
||||
void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()};
|
||||
|
||||
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
|
||||
is_speaker_auto_mute_enabled);
|
||||
|
||||
const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
}
|
||||
|
||||
void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
|
||||
const bool is_speaker_auto_mute_enabled = false;
|
||||
bool is_speaker_auto_mute_enabled{};
|
||||
const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
|
||||
|
||||
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
|
||||
is_speaker_auto_mute_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(result);
|
||||
rb.Push<u8>(is_speaker_auto_mute_enabled);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,10 @@ namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Set {
|
||||
class ISystemSettingsServer;
|
||||
}
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
class AudCtl final : public ServiceFramework<AudCtl> {
|
||||
@ -17,14 +21,6 @@ public:
|
||||
~AudCtl() override;
|
||||
|
||||
private:
|
||||
enum class AudioOutputMode {
|
||||
Invalid,
|
||||
Pcm1ch,
|
||||
Pcm2ch,
|
||||
Pcm6ch,
|
||||
PcmAuto,
|
||||
};
|
||||
|
||||
enum class ForceMutePolicy {
|
||||
Disable,
|
||||
SpeakerMuteOnHeadphoneUnplugged,
|
||||
@ -37,10 +33,18 @@ private:
|
||||
|
||||
void GetTargetVolumeMin(HLERequestContext& ctx);
|
||||
void GetTargetVolumeMax(HLERequestContext& ctx);
|
||||
void GetAudioOutputMode(HLERequestContext& ctx);
|
||||
void SetAudioOutputMode(HLERequestContext& ctx);
|
||||
void GetForceMutePolicy(HLERequestContext& ctx);
|
||||
void GetOutputModeSetting(HLERequestContext& ctx);
|
||||
void SetOutputModeSetting(HLERequestContext& ctx);
|
||||
void SetHeadphoneOutputLevelMode(HLERequestContext& ctx);
|
||||
void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
|
||||
void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx);
|
||||
void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
|
||||
void AcquireTargetNotification(HLERequestContext& ctx);
|
||||
|
||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||
};
|
||||
|
||||
} // namespace Service::Audio
|
||||
|
@ -35,10 +35,11 @@ public:
|
||||
explicit IAudioRenderer(Core::System& system_, Manager& manager_,
|
||||
AudioCore::AudioRendererParameterInternal& params,
|
||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
||||
u32 process_handle, u64 applet_resource_user_id, s32 session_id)
|
||||
u32 process_handle, Kernel::KProcess& process_,
|
||||
u64 applet_resource_user_id, s32 session_id)
|
||||
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
|
||||
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
|
||||
impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
|
||||
impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
|
||||
@ -59,13 +60,15 @@ public:
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
||||
impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
|
||||
process.Open();
|
||||
impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
|
||||
applet_resource_user_id, session_id);
|
||||
}
|
||||
|
||||
~IAudioRenderer() override {
|
||||
impl->Finalize();
|
||||
service_context.CloseEvent(rendered_event);
|
||||
process.Close();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -235,6 +238,7 @@ private:
|
||||
Kernel::KEvent* rendered_event;
|
||||
Manager& manager;
|
||||
std::unique_ptr<Renderer> impl;
|
||||
Kernel::KProcess& process;
|
||||
Common::ScratchBuffer<u8> output_buffer;
|
||||
Common::ScratchBuffer<u8> performance_buffer;
|
||||
};
|
||||
@ -455,7 +459,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)};
|
||||
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
|
||||
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
|
||||
|
||||
const auto session_id{impl->GetSessionId()};
|
||||
@ -472,7 +476,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
|
||||
transfer_memory_size, process_handle,
|
||||
transfer_memory_size, process_handle, *process,
|
||||
applet_resource_user_id, session_id);
|
||||
}
|
||||
|
||||
@ -522,7 +526,7 @@ void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
LOG_ERROR(Service_Audio, "called. Implement me!");
|
||||
}
|
||||
|
||||
void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "core/hle/service/caps/caps_a.h"
|
||||
#include "core/hle/service/caps/caps_manager.h"
|
||||
#include "core/hle/service/caps/caps_result.h"
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
@ -18,9 +18,9 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
|
||||
{0, nullptr, "GetAlbumFileCount"},
|
||||
{1, nullptr, "GetAlbumFileList"},
|
||||
{2, nullptr, "LoadAlbumFile"},
|
||||
{3, &IAlbumAccessorService::DeleteAlbumFile, "DeleteAlbumFile"},
|
||||
{3, C<&IAlbumAccessorService::DeleteAlbumFile>, "DeleteAlbumFile"},
|
||||
{4, nullptr, "StorageCopyAlbumFile"},
|
||||
{5, &IAlbumAccessorService::IsAlbumMounted, "IsAlbumMounted"},
|
||||
{5, C<&IAlbumAccessorService::IsAlbumMounted>, "IsAlbumMounted"},
|
||||
{6, nullptr, "GetAlbumUsage"},
|
||||
{7, nullptr, "GetAlbumFileSize"},
|
||||
{8, nullptr, "LoadAlbumFileThumbnail"},
|
||||
@ -33,18 +33,18 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
|
||||
{15, nullptr, "GetAlbumUsage3"},
|
||||
{16, nullptr, "GetAlbumMountResult"},
|
||||
{17, nullptr, "GetAlbumUsage16"},
|
||||
{18, &IAlbumAccessorService::Unknown18, "Unknown18"},
|
||||
{18, C<&IAlbumAccessorService::Unknown18>, "Unknown18"},
|
||||
{19, nullptr, "Unknown19"},
|
||||
{100, nullptr, "GetAlbumFileCountEx0"},
|
||||
{101, &IAlbumAccessorService::GetAlbumFileListEx0, "GetAlbumFileListEx0"},
|
||||
{101, C<&IAlbumAccessorService::GetAlbumFileListEx0>, "GetAlbumFileListEx0"},
|
||||
{202, nullptr, "SaveEditedScreenShot"},
|
||||
{301, nullptr, "GetLastThumbnail"},
|
||||
{302, nullptr, "GetLastOverlayMovieThumbnail"},
|
||||
{401, &IAlbumAccessorService::GetAutoSavingStorage, "GetAutoSavingStorage"},
|
||||
{401, C<&IAlbumAccessorService::GetAutoSavingStorage>, "GetAutoSavingStorage"},
|
||||
{501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
|
||||
{1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"},
|
||||
{1002, &IAlbumAccessorService::LoadAlbumScreenShotImageEx1, "LoadAlbumScreenShotImageEx1"},
|
||||
{1003, &IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1, "LoadAlbumScreenShotThumbnailImageEx1"},
|
||||
{1002, C<&IAlbumAccessorService::LoadAlbumScreenShotImageEx1>, "LoadAlbumScreenShotImageEx1"},
|
||||
{1003, C<&IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1>, "LoadAlbumScreenShotThumbnailImageEx1"},
|
||||
{8001, nullptr, "ForceAlbumUnmounted"},
|
||||
{8002, nullptr, "ResetAlbumMountStatus"},
|
||||
{8011, nullptr, "RefreshAlbumCache"},
|
||||
@ -62,138 +62,70 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
|
||||
|
||||
IAlbumAccessorService::~IAlbumAccessorService() = default;
|
||||
|
||||
void IAlbumAccessorService::DeleteAlbumFile(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto file_id{rp.PopRaw<AlbumFileId>()};
|
||||
|
||||
Result IAlbumAccessorService::DeleteAlbumFile(AlbumFileId file_id) {
|
||||
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}",
|
||||
file_id.application_id, file_id.storage, file_id.type);
|
||||
|
||||
Result result = manager->DeleteAlbumFile(file_id);
|
||||
result = TranslateResult(result);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
const Result result = manager->DeleteAlbumFile(file_id);
|
||||
R_RETURN(TranslateResult(result));
|
||||
}
|
||||
|
||||
void IAlbumAccessorService::IsAlbumMounted(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto storage{rp.PopEnum<AlbumStorage>()};
|
||||
|
||||
Result IAlbumAccessorService::IsAlbumMounted(Out<bool> out_is_mounted, AlbumStorage storage) {
|
||||
LOG_INFO(Service_Capture, "called, storage={}", storage);
|
||||
|
||||
Result result = manager->IsAlbumMounted(storage);
|
||||
const bool is_mounted = result.IsSuccess();
|
||||
result = TranslateResult(result);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(result);
|
||||
rb.Push<u8>(is_mounted);
|
||||
const Result result = manager->IsAlbumMounted(storage);
|
||||
*out_is_mounted = result.IsSuccess();
|
||||
R_RETURN(TranslateResult(result));
|
||||
}
|
||||
|
||||
void IAlbumAccessorService::Unknown18(HLERequestContext& ctx) {
|
||||
struct UnknownBuffer {
|
||||
INSERT_PADDING_BYTES(0x10);
|
||||
};
|
||||
static_assert(sizeof(UnknownBuffer) == 0x10, "UnknownBuffer is an invalid size");
|
||||
|
||||
Result IAlbumAccessorService::Unknown18(
|
||||
Out<u32> out_buffer_size,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_buffer) {
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called");
|
||||
|
||||
std::vector<UnknownBuffer> buffer{};
|
||||
|
||||
if (!buffer.empty()) {
|
||||
ctx.WriteBuffer(buffer);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<u32>(buffer.size()));
|
||||
*out_buffer_size = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto storage{rp.PopEnum<AlbumStorage>()};
|
||||
const auto flags{rp.Pop<u8>()};
|
||||
const auto album_entry_size{ctx.GetWriteBufferNumElements<AlbumEntry>()};
|
||||
|
||||
Result IAlbumAccessorService::GetAlbumFileListEx0(
|
||||
Out<u64> out_entries_size, AlbumStorage storage, u8 flags,
|
||||
OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries) {
|
||||
LOG_INFO(Service_Capture, "called, storage={}, flags={}", storage, flags);
|
||||
|
||||
std::vector<AlbumEntry> entries;
|
||||
Result result = manager->GetAlbumFileList(entries, storage, flags);
|
||||
result = TranslateResult(result);
|
||||
|
||||
entries.resize(std::min(album_entry_size, entries.size()));
|
||||
|
||||
if (!entries.empty()) {
|
||||
ctx.WriteBuffer(entries);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(result);
|
||||
rb.Push<u64>(entries.size());
|
||||
const Result result = manager->GetAlbumFileList(out_entries, *out_entries_size, storage, flags);
|
||||
R_RETURN(TranslateResult(result));
|
||||
}
|
||||
|
||||
void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) {
|
||||
Result IAlbumAccessorService::GetAutoSavingStorage(Out<bool> out_is_autosaving) {
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called");
|
||||
|
||||
bool is_autosaving{};
|
||||
Result result = manager->GetAutoSavingStorage(is_autosaving);
|
||||
result = TranslateResult(result);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(result);
|
||||
rb.Push<u8>(is_autosaving);
|
||||
const Result result = manager->GetAutoSavingStorage(*out_is_autosaving);
|
||||
R_RETURN(TranslateResult(result));
|
||||
}
|
||||
|
||||
void IAlbumAccessorService::LoadAlbumScreenShotImageEx1(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto file_id{rp.PopRaw<AlbumFileId>()};
|
||||
const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
|
||||
const auto image_buffer_size{ctx.GetWriteBufferSize(1)};
|
||||
|
||||
Result IAlbumAccessorService::LoadAlbumScreenShotImageEx1(
|
||||
const AlbumFileId& file_id, const ScreenShotDecodeOption& decoder_options,
|
||||
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer) {
|
||||
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
|
||||
file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
|
||||
|
||||
std::vector<u8> image;
|
||||
LoadAlbumScreenShotImageOutput image_output;
|
||||
Result result =
|
||||
manager->LoadAlbumScreenShotImage(image_output, image, file_id, decoder_options);
|
||||
result = TranslateResult(result);
|
||||
|
||||
if (image.size() > image_buffer_size) {
|
||||
result = ResultWorkMemoryError;
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
ctx.WriteBuffer(image_output, 0);
|
||||
ctx.WriteBuffer(image, 1);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
const Result result =
|
||||
manager->LoadAlbumScreenShotImage(*out_image_output, out_image, file_id, decoder_options);
|
||||
R_RETURN(TranslateResult(result));
|
||||
}
|
||||
|
||||
void IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto file_id{rp.PopRaw<AlbumFileId>()};
|
||||
const auto decoder_options{rp.PopRaw<ScreenShotDecodeOption>()};
|
||||
|
||||
Result IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(
|
||||
const AlbumFileId& file_id, const ScreenShotDecodeOption& decoder_options,
|
||||
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer) {
|
||||
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
|
||||
file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
|
||||
|
||||
std::vector<u8> image(ctx.GetWriteBufferSize(1));
|
||||
LoadAlbumScreenShotImageOutput image_output;
|
||||
Result result =
|
||||
manager->LoadAlbumScreenShotThumbnail(image_output, image, file_id, decoder_options);
|
||||
result = TranslateResult(result);
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
ctx.WriteBuffer(image_output, 0);
|
||||
ctx.WriteBuffer(image, 1);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
const Result result = manager->LoadAlbumScreenShotThumbnail(*out_image_output, out_image,
|
||||
file_id, decoder_options);
|
||||
R_RETURN(TranslateResult(result));
|
||||
}
|
||||
|
||||
Result IAlbumAccessorService::TranslateResult(Result in_result) {
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@ -19,13 +21,31 @@ public:
|
||||
~IAlbumAccessorService() override;
|
||||
|
||||
private:
|
||||
void DeleteAlbumFile(HLERequestContext& ctx);
|
||||
void IsAlbumMounted(HLERequestContext& ctx);
|
||||
void Unknown18(HLERequestContext& ctx);
|
||||
void GetAlbumFileListEx0(HLERequestContext& ctx);
|
||||
void GetAutoSavingStorage(HLERequestContext& ctx);
|
||||
void LoadAlbumScreenShotImageEx1(HLERequestContext& ctx);
|
||||
void LoadAlbumScreenShotThumbnailImageEx1(HLERequestContext& ctx);
|
||||
Result DeleteAlbumFile(AlbumFileId file_id);
|
||||
|
||||
Result IsAlbumMounted(Out<bool> out_is_mounted, AlbumStorage storage);
|
||||
|
||||
Result Unknown18(
|
||||
Out<u32> out_buffer_size,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure>
|
||||
out_buffer);
|
||||
|
||||
Result GetAlbumFileListEx0(Out<u64> out_entries_size, AlbumStorage storage, u8 flags,
|
||||
OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries);
|
||||
|
||||
Result GetAutoSavingStorage(Out<bool> out_is_autosaving);
|
||||
|
||||
Result LoadAlbumScreenShotImageEx1(
|
||||
const AlbumFileId& file_id, const ScreenShotDecodeOption& decoder_options,
|
||||
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer);
|
||||
|
||||
Result LoadAlbumScreenShotThumbnailImageEx1(
|
||||
const AlbumFileId& file_id, const ScreenShotDecodeOption& decoder_options,
|
||||
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
||||
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer);
|
||||
|
||||
Result TranslateResult(Result in_result);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "core/hle/service/caps/caps_manager.h"
|
||||
#include "core/hle/service/caps/caps_result.h"
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
@ -17,7 +18,7 @@ IAlbumControlService::IAlbumControlService(Core::System& system_,
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "CaptureRawImage"},
|
||||
{2, nullptr, "CaptureRawImageWithTimeout"},
|
||||
{33, &IAlbumControlService::SetShimLibraryVersion, "SetShimLibraryVersion"},
|
||||
{33, C<&IAlbumControlService::SetShimLibraryVersion>, "SetShimLibraryVersion"},
|
||||
{1001, nullptr, "RequestTakingScreenShot"},
|
||||
{1002, nullptr, "RequestTakingScreenShotWithTimeout"},
|
||||
{1011, nullptr, "NotifyTakingScreenShotRefused"},
|
||||
@ -42,16 +43,11 @@ IAlbumControlService::IAlbumControlService(Core::System& system_,
|
||||
|
||||
IAlbumControlService::~IAlbumControlService() = default;
|
||||
|
||||
void IAlbumControlService::SetShimLibraryVersion(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto library_version{rp.Pop<u64>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
Result IAlbumControlService::SetShimLibraryVersion(ShimLibraryVersion library_version,
|
||||
ClientAppletResourceUserId aruid) {
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
|
||||
library_version, applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
library_version, aruid.pid);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::Capture
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@ -11,6 +12,7 @@ class System;
|
||||
|
||||
namespace Service::Capture {
|
||||
class AlbumManager;
|
||||
enum class ShimLibraryVersion : u64;
|
||||
|
||||
class IAlbumControlService final : public ServiceFramework<IAlbumControlService> {
|
||||
public:
|
||||
@ -19,7 +21,8 @@ public:
|
||||
~IAlbumControlService() override;
|
||||
|
||||
private:
|
||||
void SetShimLibraryVersion(HLERequestContext& ctx);
|
||||
Result SetShimLibraryVersion(ShimLibraryVersion library_version,
|
||||
ClientAppletResourceUserId aruid);
|
||||
|
||||
std::shared_ptr<AlbumManager> manager = nullptr;
|
||||
};
|
||||
|
@ -58,8 +58,8 @@ Result AlbumManager::IsAlbumMounted(AlbumStorage storage) {
|
||||
return is_mounted ? ResultSuccess : ResultIsNotMounted;
|
||||
}
|
||||
|
||||
Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage,
|
||||
u8 flags) const {
|
||||
Result AlbumManager::GetAlbumFileList(std::span<AlbumEntry> out_entries, u64& out_entries_count,
|
||||
AlbumStorage storage, u8 flags) const {
|
||||
if (storage > AlbumStorage::Sd) {
|
||||
return ResultInvalidStorage;
|
||||
}
|
||||
@ -72,51 +72,55 @@ Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, Albu
|
||||
if (file_id.storage != storage) {
|
||||
continue;
|
||||
}
|
||||
if (out_entries.size() >= SdAlbumFileLimit) {
|
||||
if (out_entries_count >= SdAlbumFileLimit) {
|
||||
break;
|
||||
}
|
||||
if (out_entries_count >= out_entries.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto entry_size = Common::FS::GetSize(path);
|
||||
out_entries.push_back({
|
||||
out_entries[out_entries_count++] = {
|
||||
.entry_size = entry_size,
|
||||
.file_id = file_id,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
|
||||
ContentType content_type, s64 start_posix_time,
|
||||
s64 end_posix_time, u64 aruid) const {
|
||||
Result AlbumManager::GetAlbumFileList(std::span<ApplicationAlbumFileEntry> out_entries,
|
||||
u64& out_entries_count, ContentType content_type,
|
||||
s64 start_posix_time, s64 end_posix_time, u64 aruid) const {
|
||||
if (!is_mounted) {
|
||||
return ResultIsNotMounted;
|
||||
}
|
||||
|
||||
std::vector<ApplicationAlbumEntry> album_entries;
|
||||
std::vector<ApplicationAlbumEntry> album_entries(out_entries.size());
|
||||
const auto start_date = ConvertToAlbumDateTime(start_posix_time);
|
||||
const auto end_date = ConvertToAlbumDateTime(end_posix_time);
|
||||
const auto result = GetAlbumFileList(album_entries, content_type, start_date, end_date, aruid);
|
||||
const auto result = GetAlbumFileList(album_entries, out_entries_count, content_type, start_date,
|
||||
end_date, aruid);
|
||||
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const auto& album_entry : album_entries) {
|
||||
ApplicationAlbumFileEntry entry{
|
||||
.entry = album_entry,
|
||||
.datetime = album_entry.datetime,
|
||||
for (std::size_t i = 0; i < out_entries_count; i++) {
|
||||
out_entries[i] = {
|
||||
.entry = album_entries[i],
|
||||
.datetime = album_entries[i].datetime,
|
||||
.unknown = {},
|
||||
};
|
||||
out_entries.push_back(entry);
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
|
||||
ContentType content_type, AlbumFileDateTime start_date,
|
||||
AlbumFileDateTime end_date, u64 aruid) const {
|
||||
Result AlbumManager::GetAlbumFileList(std::span<ApplicationAlbumEntry> out_entries,
|
||||
u64& out_entries_count, ContentType content_type,
|
||||
AlbumFileDateTime start_date, AlbumFileDateTime end_date,
|
||||
u64 aruid) const {
|
||||
if (!is_mounted) {
|
||||
return ResultIsNotMounted;
|
||||
}
|
||||
@ -131,12 +135,15 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_en
|
||||
if (file_id.date < end_date) {
|
||||
continue;
|
||||
}
|
||||
if (out_entries.size() >= SdAlbumFileLimit) {
|
||||
if (out_entries_count >= SdAlbumFileLimit) {
|
||||
break;
|
||||
}
|
||||
if (out_entries_count >= out_entries.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto entry_size = Common::FS::GetSize(path);
|
||||
ApplicationAlbumEntry entry{
|
||||
out_entries[out_entries_count++] = {
|
||||
.size = entry_size,
|
||||
.hash{},
|
||||
.datetime = file_id.date,
|
||||
@ -144,7 +151,6 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_en
|
||||
.content = content_type,
|
||||
.unknown = 1,
|
||||
};
|
||||
out_entries.push_back(entry);
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
@ -156,8 +162,7 @@ Result AlbumManager::GetAutoSavingStorage(bool& out_is_autosaving) const {
|
||||
}
|
||||
|
||||
Result AlbumManager::LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output,
|
||||
std::vector<u8>& out_image,
|
||||
const AlbumFileId& file_id,
|
||||
std::span<u8> out_image, const AlbumFileId& file_id,
|
||||
const ScreenShotDecodeOption& decoder_options) const {
|
||||
if (file_id.storage > AlbumStorage::Sd) {
|
||||
return ResultInvalidStorage;
|
||||
@ -176,7 +181,9 @@ Result AlbumManager::LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& ou
|
||||
.orientation = AlbumImageOrientation::None,
|
||||
.unknown_1{},
|
||||
.unknown_2{},
|
||||
.pad163{},
|
||||
},
|
||||
.pad179{},
|
||||
};
|
||||
|
||||
std::filesystem::path path;
|
||||
@ -186,14 +193,12 @@ Result AlbumManager::LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& ou
|
||||
return result;
|
||||
}
|
||||
|
||||
out_image.resize(out_image_output.height * out_image_output.width * STBI_rgb_alpha);
|
||||
|
||||
return LoadImage(out_image, path, static_cast<int>(out_image_output.width),
|
||||
+static_cast<int>(out_image_output.height), decoder_options.flags);
|
||||
}
|
||||
|
||||
Result AlbumManager::LoadAlbumScreenShotThumbnail(
|
||||
LoadAlbumScreenShotImageOutput& out_image_output, std::vector<u8>& out_image,
|
||||
LoadAlbumScreenShotImageOutput& out_image_output, std::span<u8> out_image,
|
||||
const AlbumFileId& file_id, const ScreenShotDecodeOption& decoder_options) const {
|
||||
if (file_id.storage > AlbumStorage::Sd) {
|
||||
return ResultInvalidStorage;
|
||||
@ -212,7 +217,9 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail(
|
||||
.orientation = AlbumImageOrientation::None,
|
||||
.unknown_1{},
|
||||
.unknown_2{},
|
||||
.pad163{},
|
||||
},
|
||||
.pad179{},
|
||||
};
|
||||
|
||||
std::filesystem::path path;
|
||||
@ -222,8 +229,6 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail(
|
||||
return result;
|
||||
}
|
||||
|
||||
out_image.resize(out_image_output.height * out_image_output.width * STBI_rgb_alpha);
|
||||
|
||||
return LoadImage(out_image, path, static_cast<int>(out_image_output.width),
|
||||
+static_cast<int>(out_image_output.height), decoder_options.flags);
|
||||
}
|
||||
@ -246,10 +251,10 @@ Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
|
||||
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
|
||||
static_service->GetStandardUserSystemClock(user_clock);
|
||||
static_service->GetStandardUserSystemClock(&user_clock);
|
||||
|
||||
s64 posix_time{};
|
||||
auto result = user_clock->GetCurrentTime(posix_time);
|
||||
auto result = user_clock->GetCurrentTime(&posix_time);
|
||||
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
@ -268,10 +273,10 @@ Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
|
||||
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
|
||||
static_service->GetStandardUserSystemClock(user_clock);
|
||||
static_service->GetStandardUserSystemClock(&user_clock);
|
||||
|
||||
s64 posix_time{};
|
||||
auto result = user_clock->GetCurrentTime(posix_time);
|
||||
auto result = user_clock->GetCurrentTime(&posix_time);
|
||||
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
@ -470,11 +475,11 @@ AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {
|
||||
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
|
||||
|
||||
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{};
|
||||
static_service->GetTimeZoneService(timezone_service);
|
||||
static_service->GetTimeZoneService(&timezone_service);
|
||||
|
||||
Service::PSC::Time::CalendarTime calendar_time{};
|
||||
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
|
||||
timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time);
|
||||
timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time);
|
||||
|
||||
return {
|
||||
.year = calendar_time.year,
|
||||
|
@ -42,20 +42,20 @@ public:
|
||||
|
||||
Result DeleteAlbumFile(const AlbumFileId& file_id);
|
||||
Result IsAlbumMounted(AlbumStorage storage);
|
||||
Result GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage,
|
||||
u8 flags) const;
|
||||
Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
|
||||
ContentType content_type, s64 start_posix_time, s64 end_posix_time,
|
||||
u64 aruid) const;
|
||||
Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
|
||||
Result GetAlbumFileList(std::span<AlbumEntry> out_entries, u64& out_entries_count,
|
||||
AlbumStorage storage, u8 flags) const;
|
||||
Result GetAlbumFileList(std::span<ApplicationAlbumFileEntry> out_entries,
|
||||
u64& out_entries_count, ContentType content_type, s64 start_posix_time,
|
||||
s64 end_posix_time, u64 aruid) const;
|
||||
Result GetAlbumFileList(std::span<ApplicationAlbumEntry> out_entries, u64& out_entries_count,
|
||||
ContentType content_type, AlbumFileDateTime start_date,
|
||||
AlbumFileDateTime end_date, u64 aruid) const;
|
||||
Result GetAutoSavingStorage(bool& out_is_autosaving) const;
|
||||
Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output,
|
||||
std::vector<u8>& out_image, const AlbumFileId& file_id,
|
||||
std::span<u8> out_image, const AlbumFileId& file_id,
|
||||
const ScreenShotDecodeOption& decoder_options) const;
|
||||
Result LoadAlbumScreenShotThumbnail(LoadAlbumScreenShotImageOutput& out_image_output,
|
||||
std::vector<u8>& out_image, const AlbumFileId& file_id,
|
||||
std::span<u8> out_image, const AlbumFileId& file_id,
|
||||
const ScreenShotDecodeOption& decoder_options) const;
|
||||
|
||||
Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
|
||||
|
@ -3,10 +3,9 @@
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/service/caps/caps_manager.h"
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
|
||||
#include "core/hle/service/caps/caps_ss.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
|
||||
@ -17,9 +16,9 @@ IScreenShotService::IScreenShotService(Core::System& system_,
|
||||
static const FunctionInfo functions[] = {
|
||||
{201, nullptr, "SaveScreenShot"},
|
||||
{202, nullptr, "SaveEditedScreenShot"},
|
||||
{203, &IScreenShotService::SaveScreenShotEx0, "SaveScreenShotEx0"},
|
||||
{203, C<&IScreenShotService::SaveScreenShotEx0>, "SaveScreenShotEx0"},
|
||||
{204, nullptr, "SaveEditedScreenShotEx0"},
|
||||
{206, &IScreenShotService::SaveEditedScreenShotEx1, "SaveEditedScreenShotEx1"},
|
||||
{206, C<&IScreenShotService::SaveEditedScreenShotEx1>, "SaveEditedScreenShotEx1"},
|
||||
{208, nullptr, "SaveScreenShotOfMovieEx1"},
|
||||
{1000, nullptr, "Unknown1000"},
|
||||
};
|
||||
@ -30,69 +29,38 @@ IScreenShotService::IScreenShotService(Core::System& system_,
|
||||
|
||||
IScreenShotService::~IScreenShotService() = default;
|
||||
|
||||
void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
ScreenShotAttribute attribute{};
|
||||
AlbumReportOption report_option{};
|
||||
INSERT_PADDING_BYTES(0x4);
|
||||
u64 applet_resource_user_id{};
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
const auto image_data_buffer = ctx.ReadBuffer();
|
||||
|
||||
Result IScreenShotService::SaveScreenShotEx0(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute,
|
||||
AlbumReportOption report_option, ClientAppletResourceUserId aruid,
|
||||
InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer) {
|
||||
LOG_INFO(Service_Capture,
|
||||
"called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
|
||||
parameters.report_option, image_data_buffer.size(),
|
||||
parameters.applet_resource_user_id);
|
||||
report_option, image_data_buffer.size(), aruid.pid);
|
||||
|
||||
ApplicationAlbumEntry entry{};
|
||||
manager->FlipVerticallyOnWrite(false);
|
||||
const auto result =
|
||||
manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option,
|
||||
image_data_buffer, parameters.applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(result);
|
||||
rb.PushRaw(entry);
|
||||
R_RETURN(manager->SaveScreenShot(*out_entry, attribute, report_option, image_data_buffer,
|
||||
aruid.pid));
|
||||
}
|
||||
|
||||
void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
ScreenShotAttribute attribute;
|
||||
u64 width;
|
||||
u64 height;
|
||||
u64 thumbnail_width;
|
||||
u64 thumbnail_height;
|
||||
AlbumFileId file_id;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x78, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
const auto application_data_buffer = ctx.ReadBuffer(0);
|
||||
const auto image_data_buffer = ctx.ReadBuffer(1);
|
||||
const auto thumbnail_image_data_buffer = ctx.ReadBuffer(2);
|
||||
|
||||
Result IScreenShotService::SaveEditedScreenShotEx1(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute, u64 width,
|
||||
u64 height, u64 thumbnail_width, u64 thumbnail_height, const AlbumFileId& file_id,
|
||||
const InLargeData<std::array<u8, 0x400>, BufferAttr_HipcMapAlias> application_data_buffer,
|
||||
const InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer,
|
||||
const InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
thumbnail_image_data_buffer) {
|
||||
LOG_INFO(Service_Capture,
|
||||
"called, width={}, height={}, thumbnail_width={}, thumbnail_height={}, "
|
||||
"application_id={:016x}, storage={}, type={}, app_data_buffer_size={}, "
|
||||
"application_id={:016x}, storage={}, type={}, "
|
||||
"image_data_buffer_size={}, thumbnail_image_buffer_size={}",
|
||||
parameters.width, parameters.height, parameters.thumbnail_width,
|
||||
parameters.thumbnail_height, parameters.file_id.application_id,
|
||||
parameters.file_id.storage, parameters.file_id.type, application_data_buffer.size(),
|
||||
image_data_buffer.size(), thumbnail_image_data_buffer.size());
|
||||
width, height, thumbnail_width, thumbnail_height, file_id.application_id,
|
||||
file_id.storage, file_id.type, image_data_buffer.size(),
|
||||
thumbnail_image_data_buffer.size());
|
||||
|
||||
ApplicationAlbumEntry entry{};
|
||||
manager->FlipVerticallyOnWrite(false);
|
||||
const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute,
|
||||
parameters.file_id, image_data_buffer);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(result);
|
||||
rb.PushRaw(entry);
|
||||
R_RETURN(manager->SaveEditedScreenShot(*out_entry, attribute, file_id, image_data_buffer));
|
||||
}
|
||||
|
||||
} // namespace Service::Capture
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@ -17,8 +19,20 @@ public:
|
||||
~IScreenShotService() override;
|
||||
|
||||
private:
|
||||
void SaveScreenShotEx0(HLERequestContext& ctx);
|
||||
void SaveEditedScreenShotEx1(HLERequestContext& ctx);
|
||||
Result SaveScreenShotEx0(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute,
|
||||
AlbumReportOption report_option, ClientAppletResourceUserId aruid,
|
||||
InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer);
|
||||
|
||||
Result SaveEditedScreenShotEx1(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute, u64 width,
|
||||
u64 height, u64 thumbnail_width, u64 thumbnail_height, const AlbumFileId& file_id,
|
||||
const InLargeData<std::array<u8, 0x400>, BufferAttr_HipcMapAlias> application_data_buffer,
|
||||
const InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer,
|
||||
const InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
thumbnail_image_data_buffer);
|
||||
|
||||
std::shared_ptr<AlbumManager> manager;
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "core/hle/service/caps/caps_manager.h"
|
||||
#include "core/hle/service/caps/caps_su.h"
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
|
||||
@ -16,10 +17,10 @@ IScreenShotApplicationService::IScreenShotApplicationService(
|
||||
: ServiceFramework{system_, "caps:su"}, manager{album_manager} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{32, &IScreenShotApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"},
|
||||
{32, C<&IScreenShotApplicationService::SetShimLibraryVersion>, "SetShimLibraryVersion"},
|
||||
{201, nullptr, "SaveScreenShot"},
|
||||
{203, &IScreenShotApplicationService::SaveScreenShotEx0, "SaveScreenShotEx0"},
|
||||
{205, &IScreenShotApplicationService::SaveScreenShotEx1, "SaveScreenShotEx1"},
|
||||
{203, C<&IScreenShotApplicationService::SaveScreenShotEx0>, "SaveScreenShotEx0"},
|
||||
{205, C<&IScreenShotApplicationService::SaveScreenShotEx1>, "SaveScreenShotEx1"},
|
||||
{210, nullptr, "SaveScreenShotEx2"},
|
||||
};
|
||||
// clang-format on
|
||||
@ -29,77 +30,40 @@ IScreenShotApplicationService::IScreenShotApplicationService(
|
||||
|
||||
IScreenShotApplicationService::~IScreenShotApplicationService() = default;
|
||||
|
||||
void IScreenShotApplicationService::SetShimLibraryVersion(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto library_version{rp.Pop<u64>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
Result IScreenShotApplicationService::SetShimLibraryVersion(ShimLibraryVersion library_version,
|
||||
ClientAppletResourceUserId aruid) {
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
|
||||
library_version, applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
library_version, aruid.pid);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IScreenShotApplicationService::SaveScreenShotEx0(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
ScreenShotAttribute attribute{};
|
||||
AlbumReportOption report_option{};
|
||||
INSERT_PADDING_BYTES(0x4);
|
||||
u64 applet_resource_user_id{};
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
const auto image_data_buffer = ctx.ReadBuffer();
|
||||
|
||||
Result IScreenShotApplicationService::SaveScreenShotEx0(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute,
|
||||
AlbumReportOption report_option, ClientAppletResourceUserId aruid,
|
||||
InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer) {
|
||||
LOG_INFO(Service_Capture,
|
||||
"called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
|
||||
parameters.report_option, image_data_buffer.size(),
|
||||
parameters.applet_resource_user_id);
|
||||
report_option, image_data_buffer.size(), aruid.pid);
|
||||
|
||||
ApplicationAlbumEntry entry{};
|
||||
manager->FlipVerticallyOnWrite(false);
|
||||
const auto result =
|
||||
manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option,
|
||||
image_data_buffer, parameters.applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(result);
|
||||
rb.PushRaw(entry);
|
||||
R_RETURN(manager->SaveScreenShot(*out_entry, attribute, report_option, image_data_buffer,
|
||||
aruid.pid));
|
||||
}
|
||||
|
||||
void IScreenShotApplicationService::SaveScreenShotEx1(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
ScreenShotAttribute attribute{};
|
||||
AlbumReportOption report_option{};
|
||||
INSERT_PADDING_BYTES(0x4);
|
||||
u64 applet_resource_user_id{};
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
const auto app_data_buffer = ctx.ReadBuffer(0);
|
||||
const auto image_data_buffer = ctx.ReadBuffer(1);
|
||||
|
||||
Result IScreenShotApplicationService::SaveScreenShotEx1(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute,
|
||||
AlbumReportOption report_option, ClientAppletResourceUserId aruid,
|
||||
const InLargeData<ApplicationData, BufferAttr_HipcMapAlias> app_data_buffer,
|
||||
const InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer) {
|
||||
LOG_INFO(Service_Capture,
|
||||
"called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
|
||||
parameters.report_option, image_data_buffer.size(),
|
||||
parameters.applet_resource_user_id);
|
||||
report_option, image_data_buffer.size(), aruid.pid);
|
||||
|
||||
ApplicationAlbumEntry entry{};
|
||||
ApplicationData app_data{};
|
||||
std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData));
|
||||
manager->FlipVerticallyOnWrite(false);
|
||||
const auto result =
|
||||
manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option, app_data,
|
||||
image_data_buffer, parameters.applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(result);
|
||||
rb.PushRaw(entry);
|
||||
R_RETURN(manager->SaveScreenShot(*out_entry, attribute, report_option, *app_data_buffer,
|
||||
image_data_buffer, aruid.pid));
|
||||
}
|
||||
|
||||
void IScreenShotApplicationService::CaptureAndSaveScreenshot(AlbumReportOption report_option) {
|
||||
@ -112,6 +76,7 @@ void IScreenShotApplicationService::CaptureAndSaveScreenshot(AlbumReportOption r
|
||||
.orientation = Capture::AlbumImageOrientation::None,
|
||||
.unknown_1{},
|
||||
.unknown_2{},
|
||||
.pad163{},
|
||||
};
|
||||
|
||||
renderer.RequestScreenshot(
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@ -26,9 +28,19 @@ private:
|
||||
static constexpr std::size_t screenshot_height = 720;
|
||||
static constexpr std::size_t bytes_per_pixel = 4;
|
||||
|
||||
void SetShimLibraryVersion(HLERequestContext& ctx);
|
||||
void SaveScreenShotEx0(HLERequestContext& ctx);
|
||||
void SaveScreenShotEx1(HLERequestContext& ctx);
|
||||
Result SetShimLibraryVersion(ShimLibraryVersion library_version,
|
||||
ClientAppletResourceUserId aruid);
|
||||
Result SaveScreenShotEx0(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute,
|
||||
AlbumReportOption report_option, ClientAppletResourceUserId aruid,
|
||||
InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer);
|
||||
Result SaveScreenShotEx1(
|
||||
Out<ApplicationAlbumEntry> out_entry, const ScreenShotAttribute& attribute,
|
||||
AlbumReportOption report_option, ClientAppletResourceUserId aruid,
|
||||
const InLargeData<ApplicationData, BufferAttr_HipcMapAlias> app_data_buffer,
|
||||
const InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias>
|
||||
image_data_buffer);
|
||||
|
||||
std::array<u8, screenshot_width * screenshot_height * bytes_per_pixel> image_data;
|
||||
|
||||
|
@ -41,6 +41,10 @@ enum class ScreenShotDecoderFlag : u64 {
|
||||
EnableBlockSmoothing = 1 << 1,
|
||||
};
|
||||
|
||||
enum class ShimLibraryVersion : u64 {
|
||||
Version1 = 1,
|
||||
};
|
||||
|
||||
// This is nn::capsrv::AlbumFileDateTime
|
||||
struct AlbumFileDateTime {
|
||||
s16 year{};
|
||||
@ -144,19 +148,23 @@ static_assert(sizeof(ApplicationAlbumFileEntry) == 0x30,
|
||||
"ApplicationAlbumFileEntry has incorrect size.");
|
||||
|
||||
struct ApplicationData {
|
||||
std::array<u8, 0x400> data{};
|
||||
u32 data_size{};
|
||||
std::array<u8, 0x400> data;
|
||||
u32 data_size;
|
||||
};
|
||||
static_assert(sizeof(ApplicationData) == 0x404, "ApplicationData is an invalid size");
|
||||
static_assert(std::is_trivial_v<ApplicationData>,
|
||||
"ApplicationData type must be trivially copyable.");
|
||||
|
||||
struct ScreenShotAttribute {
|
||||
u32 unknown_0{};
|
||||
AlbumImageOrientation orientation{};
|
||||
u32 unknown_1{};
|
||||
u32 unknown_2{};
|
||||
INSERT_PADDING_BYTES(0x30);
|
||||
u32 unknown_0;
|
||||
AlbumImageOrientation orientation;
|
||||
u32 unknown_1;
|
||||
u32 unknown_2;
|
||||
INSERT_PADDING_BYTES_NOINIT(0x30);
|
||||
};
|
||||
static_assert(sizeof(ScreenShotAttribute) == 0x40, "ScreenShotAttribute is an invalid size");
|
||||
static_assert(std::is_trivial_v<ScreenShotAttribute>,
|
||||
"ScreenShotAttribute type must be trivially copyable.");
|
||||
|
||||
struct ScreenShotDecodeOption {
|
||||
ScreenShotDecoderFlag flags{};
|
||||
@ -165,13 +173,15 @@ struct ScreenShotDecodeOption {
|
||||
static_assert(sizeof(ScreenShotDecodeOption) == 0x20, "ScreenShotDecodeOption is an invalid size");
|
||||
|
||||
struct LoadAlbumScreenShotImageOutput {
|
||||
s64 width{};
|
||||
s64 height{};
|
||||
ScreenShotAttribute attribute{};
|
||||
INSERT_PADDING_BYTES(0x400);
|
||||
s64 width;
|
||||
s64 height;
|
||||
ScreenShotAttribute attribute;
|
||||
INSERT_PADDING_BYTES_NOINIT(0x400);
|
||||
};
|
||||
static_assert(sizeof(LoadAlbumScreenShotImageOutput) == 0x450,
|
||||
"LoadAlbumScreenShotImageOutput is an invalid size");
|
||||
static_assert(std::is_trivial_v<LoadAlbumScreenShotImageOutput>,
|
||||
"LoadAlbumScreenShotImageOutput type must be trivially copyable.");
|
||||
|
||||
struct LoadAlbumScreenShotImageOutputForApplication {
|
||||
s64 width{};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "core/hle/service/caps/caps_manager.h"
|
||||
#include "core/hle/service/caps/caps_types.h"
|
||||
#include "core/hle/service/caps/caps_u.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
@ -14,8 +15,8 @@ IAlbumApplicationService::IAlbumApplicationService(Core::System& system_,
|
||||
: ServiceFramework{system_, "caps:u"}, manager{album_manager} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{32, &IAlbumApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"},
|
||||
{102, &IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated, "GetAlbumFileList0AafeAruidDeprecated"},
|
||||
{32, C<&IAlbumApplicationService::SetShimLibraryVersion>, "SetShimLibraryVersion"},
|
||||
{102, C<&IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated>, "GetAlbumFileList0AafeAruidDeprecated"},
|
||||
{103, nullptr, "DeleteAlbumFileByAruid"},
|
||||
{104, nullptr, "GetAlbumFileSizeByAruid"},
|
||||
{105, nullptr, "DeleteAlbumFileByAruidForDebug"},
|
||||
@ -24,7 +25,7 @@ IAlbumApplicationService::IAlbumApplicationService(Core::System& system_,
|
||||
{130, nullptr, "PrecheckToCreateContentsByAruid"},
|
||||
{140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
|
||||
{141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
|
||||
{142, &IAlbumApplicationService::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"},
|
||||
{142, C<&IAlbumApplicationService::GetAlbumFileList3AaeAruid>, "GetAlbumFileList3AaeAruid"},
|
||||
{143, nullptr, "GetAlbumFileList4AaeUidAruid"},
|
||||
{144, nullptr, "GetAllAlbumFileList3AaeAruid"},
|
||||
{60002, nullptr, "OpenAccessorSessionForApplication"},
|
||||
@ -36,101 +37,40 @@ IAlbumApplicationService::IAlbumApplicationService(Core::System& system_,
|
||||
|
||||
IAlbumApplicationService::~IAlbumApplicationService() = default;
|
||||
|
||||
void IAlbumApplicationService::SetShimLibraryVersion(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto library_version{rp.Pop<u64>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
Result IAlbumApplicationService::SetShimLibraryVersion(ShimLibraryVersion library_version,
|
||||
ClientAppletResourceUserId aruid) {
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
|
||||
library_version, applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
library_version, aruid.pid);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
ContentType content_type;
|
||||
INSERT_PADDING_BYTES(7);
|
||||
s64 start_posix_time;
|
||||
s64 end_posix_time;
|
||||
u64 applet_resource_user_id;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
Result IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated(
|
||||
Out<u64> out_entries_count, ContentType content_type, s64 start_posix_time, s64 end_posix_time,
|
||||
ClientAppletResourceUserId aruid,
|
||||
OutArray<ApplicationAlbumFileEntry, BufferAttr_HipcMapAlias> out_entries) {
|
||||
LOG_WARNING(Service_Capture,
|
||||
"(STUBBED) called. content_type={}, start_posix_time={}, end_posix_time={}, "
|
||||
"applet_resource_user_id={}",
|
||||
parameters.content_type, parameters.start_posix_time, parameters.end_posix_time,
|
||||
parameters.applet_resource_user_id);
|
||||
content_type, start_posix_time, end_posix_time, aruid.pid);
|
||||
|
||||
Result result = ResultSuccess;
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager->IsAlbumMounted(AlbumStorage::Sd);
|
||||
}
|
||||
|
||||
std::vector<ApplicationAlbumFileEntry> entries;
|
||||
if (result.IsSuccess()) {
|
||||
result = manager->GetAlbumFileList(entries, parameters.content_type,
|
||||
parameters.start_posix_time, parameters.end_posix_time,
|
||||
parameters.applet_resource_user_id);
|
||||
}
|
||||
|
||||
if (!entries.empty()) {
|
||||
ctx.WriteBuffer(entries);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(result);
|
||||
rb.Push<u64>(entries.size());
|
||||
R_TRY(manager->IsAlbumMounted(AlbumStorage::Sd));
|
||||
R_RETURN(manager->GetAlbumFileList(out_entries, *out_entries_count, content_type,
|
||||
start_posix_time, end_posix_time, aruid.pid));
|
||||
}
|
||||
|
||||
void IAlbumApplicationService::GetAlbumFileList3AaeAruid(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
ContentType content_type;
|
||||
INSERT_PADDING_BYTES(1);
|
||||
AlbumFileDateTime start_date_time;
|
||||
AlbumFileDateTime end_date_time;
|
||||
INSERT_PADDING_BYTES(6);
|
||||
u64 applet_resource_user_id;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
Result IAlbumApplicationService::GetAlbumFileList3AaeAruid(
|
||||
Out<u64> out_entries_count, ContentType content_type, AlbumFileDateTime start_date_time,
|
||||
AlbumFileDateTime end_date_time, ClientAppletResourceUserId aruid,
|
||||
OutArray<ApplicationAlbumEntry, BufferAttr_HipcMapAlias> out_entries) {
|
||||
LOG_WARNING(Service_Capture,
|
||||
"(STUBBED) called. content_type={}, start_date={}/{}/{}, "
|
||||
"end_date={}/{}/{}, applet_resource_user_id={}",
|
||||
parameters.content_type, parameters.start_date_time.year,
|
||||
parameters.start_date_time.month, parameters.start_date_time.day,
|
||||
parameters.end_date_time.year, parameters.end_date_time.month,
|
||||
parameters.end_date_time.day, parameters.applet_resource_user_id);
|
||||
content_type, start_date_time.year, start_date_time.month, start_date_time.day,
|
||||
end_date_time.year, end_date_time.month, end_date_time.day, aruid.pid);
|
||||
|
||||
Result result = ResultSuccess;
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager->IsAlbumMounted(AlbumStorage::Sd);
|
||||
}
|
||||
|
||||
std::vector<ApplicationAlbumEntry> entries;
|
||||
if (result.IsSuccess()) {
|
||||
result =
|
||||
manager->GetAlbumFileList(entries, parameters.content_type, parameters.start_date_time,
|
||||
parameters.end_date_time, parameters.applet_resource_user_id);
|
||||
}
|
||||
|
||||
if (!entries.empty()) {
|
||||
ctx.WriteBuffer(entries);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(result);
|
||||
rb.Push<u64>(entries.size());
|
||||
R_TRY(manager->IsAlbumMounted(AlbumStorage::Sd));
|
||||
R_RETURN(manager->GetAlbumFileList(out_entries, *out_entries_count, content_type,
|
||||
start_date_time, end_date_time, aruid.pid));
|
||||
}
|
||||
|
||||
} // namespace Service::Capture
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@ -19,9 +20,18 @@ public:
|
||||
~IAlbumApplicationService() override;
|
||||
|
||||
private:
|
||||
void SetShimLibraryVersion(HLERequestContext& ctx);
|
||||
void GetAlbumFileList0AafeAruidDeprecated(HLERequestContext& ctx);
|
||||
void GetAlbumFileList3AaeAruid(HLERequestContext& ctx);
|
||||
Result SetShimLibraryVersion(ShimLibraryVersion library_version,
|
||||
ClientAppletResourceUserId aruid);
|
||||
|
||||
Result GetAlbumFileList0AafeAruidDeprecated(
|
||||
Out<u64> out_entries_count, ContentType content_type, s64 start_posix_time,
|
||||
s64 end_posix_time, ClientAppletResourceUserId aruid,
|
||||
OutArray<ApplicationAlbumFileEntry, BufferAttr_HipcMapAlias> out_entries);
|
||||
|
||||
Result GetAlbumFileList3AaeAruid(
|
||||
Out<u64> out_entries_count, ContentType content_type, AlbumFileDateTime start_date_time,
|
||||
AlbumFileDateTime end_date_time, ClientAppletResourceUserId aruid,
|
||||
OutArray<ApplicationAlbumEntry, BufferAttr_HipcMapAlias> out_entries);
|
||||
|
||||
std::shared_ptr<AlbumManager> manager = nullptr;
|
||||
};
|
||||
|
@ -12,6 +12,109 @@
|
||||
namespace Service {
|
||||
|
||||
// clang-format off
|
||||
template <typename T>
|
||||
struct UnwrapArg {
|
||||
using Type = std::remove_cvref_t<T>;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
struct UnwrapArg<InLargeData<T, A>> {
|
||||
using Type = std::remove_cv_t<typename InLargeData<T, A>::Type>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapArg<Out<T>> {
|
||||
using Type = AutoOut<typename Out<T>::Type>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapArg<OutCopyHandle<T>> {
|
||||
using Type = AutoOut<typename OutCopyHandle<T>::Type>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapArg<OutMoveHandle<T>> {
|
||||
using Type = AutoOut<typename OutMoveHandle<T>::Type>;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
struct UnwrapArg<OutLargeData<T, A>> {
|
||||
using Type = AutoOut<typename OutLargeData<T, A>::Type>;
|
||||
};
|
||||
|
||||
enum class ArgumentType {
|
||||
InProcessId,
|
||||
InData,
|
||||
InInterface,
|
||||
InCopyHandle,
|
||||
OutData,
|
||||
OutInterface,
|
||||
OutCopyHandle,
|
||||
OutMoveHandle,
|
||||
InBuffer,
|
||||
InLargeData,
|
||||
OutBuffer,
|
||||
OutLargeData,
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits;
|
||||
|
||||
template <>
|
||||
struct ArgumentTraits<ClientProcessId> {
|
||||
static constexpr ArgumentType Type = ArgumentType::InProcessId;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<SharedPointer<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::InInterface;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<InCopyHandle<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::InCopyHandle;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<Out<SharedPointer<T>>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutInterface;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<Out<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutData;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<OutCopyHandle<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutCopyHandle;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<OutMoveHandle<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutMoveHandle;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
struct ArgumentTraits<Buffer<T, A>> {
|
||||
static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
struct ArgumentTraits<InLargeData<T, A>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::InLargeData;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
struct ArgumentTraits<OutLargeData<T, A>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutLargeData;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits {
|
||||
static constexpr ArgumentType Type = ArgumentType::InData;
|
||||
};
|
||||
|
||||
struct RequestLayout {
|
||||
u32 copy_handle_count;
|
||||
u32 move_handle_count;
|
||||
@ -19,14 +122,14 @@ struct RequestLayout {
|
||||
u32 domain_interface_count;
|
||||
};
|
||||
|
||||
template <ArgumentType Type1, ArgumentType Type2, typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||
constexpr u32 GetArgumentRawDataSize() {
|
||||
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||
constexpr u32 GetInRawDataSize() {
|
||||
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
||||
return static_cast<u32>(DataOffset);
|
||||
} else {
|
||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == Type1 || ArgumentTraits<ArgType>::Type == Type2) {
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InData || ArgumentTraits<ArgType>::Type == ArgumentType::InProcessId) {
|
||||
constexpr size_t ArgAlign = alignof(ArgType);
|
||||
constexpr size_t ArgSize = sizeof(ArgType);
|
||||
|
||||
@ -35,9 +138,33 @@ constexpr u32 GetArgumentRawDataSize() {
|
||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||
|
||||
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||
return GetInRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||
} else {
|
||||
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||
return GetInRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||
constexpr u32 GetOutRawDataSize() {
|
||||
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
||||
return static_cast<u32>(DataOffset);
|
||||
} else {
|
||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
||||
using RawArgType = typename ArgType::Type;
|
||||
constexpr size_t ArgAlign = alignof(RawArgType);
|
||||
constexpr size_t ArgSize = sizeof(RawArgType);
|
||||
|
||||
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
||||
|
||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||
|
||||
return GetOutRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||
} else {
|
||||
return GetOutRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,7 +189,7 @@ constexpr RequestLayout GetNonDomainReplyInLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = 0,
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = 0,
|
||||
};
|
||||
}
|
||||
@ -72,7 +199,7 @@ constexpr RequestLayout GetDomainReplyInLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = 0,
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(),
|
||||
};
|
||||
}
|
||||
@ -82,7 +209,7 @@ constexpr RequestLayout GetNonDomainReplyOutLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = 0,
|
||||
};
|
||||
}
|
||||
@ -92,7 +219,7 @@ constexpr RequestLayout GetDomainReplyOutLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||
};
|
||||
}
|
||||
@ -122,6 +249,8 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
||||
|
||||
static_assert(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment");
|
||||
static_assert(!RawDataFinished, "All input interface arguments must appear after raw data");
|
||||
static_assert(!std::is_pointer_v<ArgType>, "Input raw data must not be a pointer");
|
||||
static_assert(std::is_trivially_copyable_v<ArgType>, "Input raw data must be trivially copyable");
|
||||
|
||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||
@ -154,7 +283,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
||||
|
||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
||||
constexpr size_t BufferSize = sizeof(ArgType);
|
||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||
|
||||
// Clear the existing data.
|
||||
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
||||
@ -195,10 +324,10 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
||||
|
||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||
constexpr size_t BufferSize = sizeof(ArgType);
|
||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||
|
||||
// Clear the existing data.
|
||||
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
||||
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
|
||||
|
||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
|
||||
@ -232,36 +361,40 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
|
||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
||||
constexpr size_t ArgAlign = alignof(ArgType);
|
||||
constexpr size_t ArgSize = sizeof(ArgType);
|
||||
using RawArgType = decltype(std::get<ArgIndex>(args).raw);
|
||||
constexpr size_t ArgAlign = alignof(RawArgType);
|
||||
constexpr size_t ArgSize = sizeof(RawArgType);
|
||||
|
||||
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
||||
static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
|
||||
static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
|
||||
static_assert(!std::is_pointer_v<RawArgType>, "Output raw data must not be a pointer");
|
||||
static_assert(std::is_trivially_copyable_v<RawArgType>, "Output raw data must be trivially copyable");
|
||||
|
||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||
|
||||
std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize);
|
||||
std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args).raw, ArgSize);
|
||||
|
||||
return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) {
|
||||
if (is_domain) {
|
||||
ctx.AddDomainObject(std::get<ArgIndex>(args));
|
||||
ctx.AddDomainObject(std::get<ArgIndex>(args).raw);
|
||||
} else {
|
||||
ctx.AddMoveInterface(std::get<ArgIndex>(args));
|
||||
ctx.AddMoveInterface(std::get<ArgIndex>(args).raw);
|
||||
}
|
||||
|
||||
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) {
|
||||
ctx.AddCopyObject(std::get<ArgIndex>(args));
|
||||
ctx.AddCopyObject(std::get<ArgIndex>(args).raw);
|
||||
|
||||
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) {
|
||||
ctx.AddMoveObject(std::get<ArgIndex>(args));
|
||||
ctx.AddMoveObject(std::get<ArgIndex>(args).raw);
|
||||
|
||||
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||
constexpr size_t BufferSize = sizeof(ArgType);
|
||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||
|
||||
ASSERT(ctx.CanWriteBuffer(OutBufferIndex));
|
||||
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
|
||||
@ -302,10 +435,10 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
|
||||
}
|
||||
const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false;
|
||||
|
||||
using MethodArguments = std::tuple<std::remove_reference_t<A>...>;
|
||||
using MethodArguments = std::tuple<std::remove_cvref_t<A>...>;
|
||||
|
||||
OutTemporaryBuffers buffers{};
|
||||
auto call_arguments = std::tuple<typename RemoveOut<A>::Type...>();
|
||||
auto call_arguments = std::tuple<typename UnwrapArg<A>::Type...>();
|
||||
|
||||
// Read inputs.
|
||||
const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2;
|
||||
|
@ -12,22 +12,31 @@
|
||||
namespace Service {
|
||||
|
||||
// clang-format off
|
||||
template <typename T>
|
||||
struct AutoOut {
|
||||
T raw;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Out {
|
||||
public:
|
||||
using Type = T;
|
||||
|
||||
/* implicit */ Out(Type& t) : raw(&t) {}
|
||||
~Out() = default;
|
||||
/* implicit */ Out(AutoOut<Type>& t) : raw(&t.raw) {}
|
||||
/* implicit */ Out(Type* t) : raw(t) {}
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
Type& operator*() {
|
||||
Type& operator*() const {
|
||||
return *raw;
|
||||
}
|
||||
|
||||
Type* operator->() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
@ -35,6 +44,9 @@ private:
|
||||
template <typename T>
|
||||
using SharedPointer = std::shared_ptr<T>;
|
||||
|
||||
template <typename T>
|
||||
using OutInterface = Out<SharedPointer<T>>;
|
||||
|
||||
struct ClientProcessId {
|
||||
explicit operator bool() const {
|
||||
return pid != 0;
|
||||
@ -101,17 +113,21 @@ class OutCopyHandle {
|
||||
public:
|
||||
using Type = T*;
|
||||
|
||||
/* implicit */ OutCopyHandle(Type& t) : raw(&t) {}
|
||||
~OutCopyHandle() = default;
|
||||
/* implicit */ OutCopyHandle(AutoOut<Type>& t) : raw(&t.raw) {}
|
||||
/* implicit */ OutCopyHandle(Type* t) : raw(t) {}
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
Type& operator*() {
|
||||
Type& operator*() const {
|
||||
return *raw;
|
||||
}
|
||||
|
||||
Type* operator->() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
@ -121,30 +137,34 @@ class OutMoveHandle {
|
||||
public:
|
||||
using Type = T*;
|
||||
|
||||
/* implicit */ OutMoveHandle(Type& t) : raw(&t) {}
|
||||
~OutMoveHandle() = default;
|
||||
/* implicit */ OutMoveHandle(AutoOut<Type>& t) : raw(&t.raw) {}
|
||||
/* implicit */ OutMoveHandle(Type* t) : raw(t) {}
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
Type& operator*() {
|
||||
Type& operator*() const {
|
||||
return *raw;
|
||||
}
|
||||
|
||||
Type* operator->() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
|
||||
enum BufferAttr : int {
|
||||
BufferAttr_In = (1U << 0),
|
||||
BufferAttr_Out = (1U << 1),
|
||||
BufferAttr_HipcMapAlias = (1U << 2),
|
||||
BufferAttr_HipcPointer = (1U << 3),
|
||||
BufferAttr_FixedSize = (1U << 4),
|
||||
BufferAttr_HipcAutoSelect = (1U << 5),
|
||||
BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6),
|
||||
BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7),
|
||||
/* 0x01 */ BufferAttr_In = (1U << 0),
|
||||
/* 0x02 */ BufferAttr_Out = (1U << 1),
|
||||
/* 0x04 */ BufferAttr_HipcMapAlias = (1U << 2),
|
||||
/* 0x08 */ BufferAttr_HipcPointer = (1U << 3),
|
||||
/* 0x10 */ BufferAttr_FixedSize = (1U << 4),
|
||||
/* 0x20 */ BufferAttr_HipcAutoSelect = (1U << 5),
|
||||
/* 0x40 */ BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6),
|
||||
/* 0x80 */ BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7),
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
@ -172,123 +192,80 @@ struct Buffer : public std::span<T> {
|
||||
}
|
||||
};
|
||||
|
||||
template <BufferAttr A>
|
||||
template <int A>
|
||||
using InBuffer = Buffer<const u8, BufferAttr_In | A>;
|
||||
|
||||
template <typename T, BufferAttr A>
|
||||
template <typename T, int A>
|
||||
using InArray = Buffer<T, BufferAttr_In | A>;
|
||||
|
||||
template <BufferAttr A>
|
||||
template <int A>
|
||||
using OutBuffer = Buffer<u8, BufferAttr_Out | A>;
|
||||
|
||||
template <typename T, BufferAttr A>
|
||||
template <typename T, int A>
|
||||
using OutArray = Buffer<T, BufferAttr_Out | A>;
|
||||
|
||||
template <typename T, int A>
|
||||
struct LargeData : public T {
|
||||
class InLargeData {
|
||||
public:
|
||||
static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
|
||||
static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize");
|
||||
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out");
|
||||
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
|
||||
static_assert((A & BufferAttr_Out) == 0, "InLargeData attr must not be Out");
|
||||
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize);
|
||||
using Type = const T;
|
||||
|
||||
/* implicit */ InLargeData(Type& t) : raw(&t) {}
|
||||
~InLargeData() = default;
|
||||
|
||||
InLargeData& operator=(Type* rhs) {
|
||||
raw = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
Type& operator*() const {
|
||||
return *raw;
|
||||
}
|
||||
|
||||
Type* operator->() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return raw != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
class OutLargeData {
|
||||
public:
|
||||
static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
|
||||
static_assert((A & BufferAttr_In) == 0, "OutLargeData attr must not be In");
|
||||
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize);
|
||||
using Type = T;
|
||||
|
||||
/* implicit */ LargeData(const T& rhs) : T(rhs) {}
|
||||
/* implicit */ LargeData() = default;
|
||||
};
|
||||
/* implicit */ OutLargeData(Type* t) : raw(t) {}
|
||||
/* implicit */ OutLargeData(AutoOut<T>& t) : raw(&t.raw) {}
|
||||
|
||||
template <typename T, BufferAttr A>
|
||||
using InLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_In | A>;
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
template <typename T, BufferAttr A>
|
||||
using OutLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_Out | A>;
|
||||
Type& operator*() const {
|
||||
return *raw;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct RemoveOut {
|
||||
using Type = std::remove_reference_t<T>;
|
||||
};
|
||||
Type* operator->() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct RemoveOut<Out<T>> {
|
||||
using Type = typename Out<T>::Type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveOut<OutCopyHandle<T>> {
|
||||
using Type = typename OutCopyHandle<T>::Type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveOut<OutMoveHandle<T>> {
|
||||
using Type = typename OutMoveHandle<T>::Type;
|
||||
};
|
||||
|
||||
enum class ArgumentType {
|
||||
InProcessId,
|
||||
InData,
|
||||
InInterface,
|
||||
InCopyHandle,
|
||||
OutData,
|
||||
OutInterface,
|
||||
OutCopyHandle,
|
||||
OutMoveHandle,
|
||||
InBuffer,
|
||||
InLargeData,
|
||||
OutBuffer,
|
||||
OutLargeData,
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits;
|
||||
|
||||
template <>
|
||||
struct ArgumentTraits<ClientProcessId> {
|
||||
static constexpr ArgumentType Type = ArgumentType::InProcessId;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<SharedPointer<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::InInterface;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<InCopyHandle<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::InCopyHandle;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<Out<SharedPointer<T>>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutInterface;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<Out<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutData;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<OutCopyHandle<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutCopyHandle;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits<OutMoveHandle<T>> {
|
||||
static constexpr ArgumentType Type = ArgumentType::OutMoveHandle;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
struct ArgumentTraits<Buffer<T, A>> {
|
||||
static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer;
|
||||
};
|
||||
|
||||
template <typename T, int A>
|
||||
struct ArgumentTraits<LargeData<T, A>> {
|
||||
static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutLargeData : ArgumentType::InLargeData;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgumentTraits {
|
||||
static constexpr ArgumentType Type = ArgumentType::InData;
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
} // namespace Service
|
||||
} // namespace Service
|
@ -41,7 +41,7 @@ bool AlarmWorker::GetClosestAlarmInfo(Service::PSC::Time::AlarmInfo& out_alarm_i
|
||||
Service::PSC::Time::AlarmInfo alarm_info{};
|
||||
s64 closest_time{};
|
||||
|
||||
auto res = m_time_m->GetClosestAlarmInfo(is_valid, alarm_info, closest_time);
|
||||
auto res = m_time_m->GetClosestAlarmInfo(&is_valid, &alarm_info, &closest_time);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
if (is_valid) {
|
||||
@ -76,6 +76,7 @@ void AlarmWorker::OnPowerStateChanged() {
|
||||
|
||||
Result AlarmWorker::AttachToClosestAlarmEvent() {
|
||||
m_time_m->GetClosestAlarmUpdatedEvent(&m_event);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
|
||||
void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m);
|
||||
|
||||
Kernel::KEvent& GetEvent() {
|
||||
Kernel::KReadableEvent& GetEvent() {
|
||||
return *m_event;
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ private:
|
||||
KernelHelpers::ServiceContext m_ctx;
|
||||
std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m;
|
||||
|
||||
Kernel::KEvent* m_event{};
|
||||
Kernel::KReadableEvent* m_event{};
|
||||
Kernel::KEvent* m_timer_event{};
|
||||
std::shared_ptr<Core::Timing::EventType> m_timer_timing_event;
|
||||
StandardSteadyClockResource& m_steady_clock_resource;
|
||||
|
@ -13,8 +13,8 @@ void FileTimestampWorker::SetFilesystemPosixTime() {
|
||||
Service::PSC::Time::CalendarTime calendar_time{};
|
||||
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
|
||||
|
||||
if (m_initialized && m_system_clock->GetCurrentTime(time) == ResultSuccess &&
|
||||
m_time_zone->ToCalendarTimeWithMyRule(calendar_time, additional_info, time) ==
|
||||
if (m_initialized && m_system_clock->GetCurrentTime(&time) == ResultSuccess &&
|
||||
m_time_zone->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, time) ==
|
||||
ResultSuccess) {
|
||||
// TODO IFileSystemProxy::SetCurrentPosixTime
|
||||
}
|
||||
|
@ -79,18 +79,18 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN
|
||||
auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
|
||||
|
||||
Service::PSC::Time::LocationName configured_name{};
|
||||
std::memcpy(configured_name.name.data(), configured_zone.data(),
|
||||
std::min(configured_name.name.size(), configured_zone.size()));
|
||||
std::memcpy(configured_name.data(), configured_zone.data(),
|
||||
std::min(configured_name.size(), configured_zone.size()));
|
||||
|
||||
if (!IsTimeZoneBinaryValid(configured_name)) {
|
||||
configured_zone = Common::TimeZone::FindSystemTimeZone();
|
||||
configured_name = {};
|
||||
std::memcpy(configured_name.name.data(), configured_zone.data(),
|
||||
std::min(configured_name.name.size(), configured_zone.size()));
|
||||
std::memcpy(configured_name.data(), configured_zone.data(),
|
||||
std::min(configured_name.size(), configured_zone.size()));
|
||||
}
|
||||
|
||||
ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!",
|
||||
configured_name.name.data());
|
||||
configured_name.data());
|
||||
|
||||
return configured_name;
|
||||
}
|
||||
@ -103,7 +103,7 @@ TimeManager::TimeManager(Core::System& system)
|
||||
m_time_m =
|
||||
system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true);
|
||||
|
||||
auto res = m_time_m->GetStaticServiceAsServiceManager(m_time_sm);
|
||||
auto res = m_time_m->GetStaticServiceAsServiceManager(&m_time_sm);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
m_set_sys =
|
||||
@ -114,10 +114,10 @@ TimeManager::TimeManager(Core::System& system)
|
||||
|
||||
m_worker.Initialize(m_time_sm, m_set_sys);
|
||||
|
||||
res = m_time_sm->GetStandardUserSystemClock(m_file_timestamp_worker.m_system_clock);
|
||||
res = m_time_sm->GetStandardUserSystemClock(&m_file_timestamp_worker.m_system_clock);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
res = m_time_sm->GetTimeZoneService(m_file_timestamp_worker.m_time_zone);
|
||||
res = m_time_sm->GetTimeZoneService(&m_file_timestamp_worker.m_time_zone);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
res = SetupStandardSteadyClockCore();
|
||||
@ -161,8 +161,8 @@ TimeManager::TimeManager(Core::System& system)
|
||||
automatic_correction_time_point);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
res = m_time_m->SetupStandardUserSystemClockCore(automatic_correction_time_point,
|
||||
is_automatic_correction_enabled);
|
||||
res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled,
|
||||
automatic_correction_time_point);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
res = m_time_m->SetupEphemeralNetworkSystemClockCore();
|
||||
@ -184,12 +184,12 @@ TimeManager::TimeManager(Core::System& system)
|
||||
m_file_timestamp_worker.m_initialized = true;
|
||||
|
||||
s64 system_clock_time{};
|
||||
if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(system_clock_time) ==
|
||||
if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(&system_clock_time) ==
|
||||
ResultSuccess) {
|
||||
Service::PSC::Time::CalendarTime calendar_time{};
|
||||
Service::PSC::Time::CalendarAdditionalInfo calendar_additional{};
|
||||
if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule(
|
||||
calendar_time, calendar_additional, system_clock_time) == ResultSuccess) {
|
||||
&calendar_time, &calendar_additional, system_clock_time) == ResultSuccess) {
|
||||
// TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time,
|
||||
// calendar_additional.ut_offset)
|
||||
}
|
||||
@ -228,10 +228,9 @@ Result TimeManager::SetupStandardSteadyClockCore() {
|
||||
m_set_sys->SetExternalSteadyClockSourceId(clock_source_id);
|
||||
}
|
||||
|
||||
res = m_time_m->SetupStandardSteadyClockCore(clock_source_id, m_steady_clock_resource.GetTime(),
|
||||
external_steady_clock_internal_offset_ns,
|
||||
standard_steady_clock_test_offset_ns,
|
||||
reset_detected);
|
||||
res = m_time_m->SetupStandardSteadyClockCore(
|
||||
reset_detected, clock_source_id, m_steady_clock_resource.GetTime(),
|
||||
external_steady_clock_internal_offset_ns, standard_steady_clock_test_offset_ns);
|
||||
ASSERT(res == ResultSuccess);
|
||||
R_SUCCEED();
|
||||
}
|
||||
@ -243,14 +242,15 @@ Result TimeManager::SetupTimeZoneServiceCore() {
|
||||
|
||||
auto configured_zone = GetTimeZoneString(name);
|
||||
|
||||
if (configured_zone.name != name.name) {
|
||||
if (configured_zone != name) {
|
||||
m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
|
||||
name = configured_zone;
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
|
||||
m_time_sm->GetStandardLocalSystemClock(local_clock);
|
||||
m_time_sm->GetStandardLocalSystemClock(&local_clock);
|
||||
|
||||
Service::PSC::Time::SystemClockContext context{};
|
||||
local_clock->GetSystemClockContext(context);
|
||||
local_clock->GetSystemClockContext(&context);
|
||||
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point);
|
||||
}
|
||||
|
||||
@ -267,7 +267,7 @@ Result TimeManager::SetupTimeZoneServiceCore() {
|
||||
res = GetTimeZoneRule(rule_buffer, rule_size, name);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
res = m_time_m->SetupTimeZoneServiceCore(name, time_point, rule_version, location_count,
|
||||
res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point,
|
||||
rule_buffer);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
|
@ -3,9 +3,11 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/glue/time/file_timestamp_worker.h"
|
||||
#include "core/hle/service/glue/time/static.h"
|
||||
#include "core/hle/service/psc/time/errors.h"
|
||||
@ -41,25 +43,25 @@ StaticService::StaticService(Core::System& system_,
|
||||
time->m_steady_clock_resource} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||
{1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
||||
{2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"},
|
||||
{20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
|
||||
{50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"},
|
||||
{51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"},
|
||||
{100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||
{300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"},
|
||||
{401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"},
|
||||
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
|
||||
{1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"},
|
||||
{2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"},
|
||||
{3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"},
|
||||
{4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"},
|
||||
{5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"},
|
||||
{20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
|
||||
{50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"},
|
||||
{51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"},
|
||||
{100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||
{300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"},
|
||||
{401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@ -71,314 +73,80 @@ StaticService::StaticService(Core::System& system_,
|
||||
if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock &&
|
||||
!m_setup_info.can_write_network_clock && m_setup_info.can_write_timezone_device_location &&
|
||||
!m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) {
|
||||
m_time_m->GetStaticServiceAsAdmin(m_wrapped_service);
|
||||
m_time_m->GetStaticServiceAsAdmin(&m_wrapped_service);
|
||||
} else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock &&
|
||||
!m_setup_info.can_write_network_clock &&
|
||||
!m_setup_info.can_write_timezone_device_location &&
|
||||
!m_setup_info.can_write_steady_clock &&
|
||||
!m_setup_info.can_write_uninitialized_clock) {
|
||||
m_time_m->GetStaticServiceAsUser(m_wrapped_service);
|
||||
m_time_m->GetStaticServiceAsUser(&m_wrapped_service);
|
||||
} else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock &&
|
||||
!m_setup_info.can_write_network_clock &&
|
||||
!m_setup_info.can_write_timezone_device_location &&
|
||||
m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) {
|
||||
m_time_m->GetStaticServiceAsRepair(m_wrapped_service);
|
||||
m_time_m->GetStaticServiceAsRepair(&m_wrapped_service);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
auto res = m_wrapped_service->GetTimeZoneService(m_time_zone);
|
||||
auto res = m_wrapped_service->GetTimeZoneService(&m_time_zone);
|
||||
ASSERT(res == ResultSuccess);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
|
||||
auto res = GetStandardUserSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
|
||||
auto res = GetStandardNetworkSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SteadyClock> service{};
|
||||
auto res = GetStandardSteadyClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<TimeZoneService> service{};
|
||||
auto res = GetTimeZoneService(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
|
||||
auto res = GetStandardLocalSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
|
||||
auto res = GetEphemeralNetworkSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KSharedMemory* shared_memory{};
|
||||
auto res = GetSharedMemoryNativeHandle(&shared_memory);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(shared_memory);
|
||||
}
|
||||
|
||||
void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto offset_ns{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetStandardSteadyClockInternalOffset(offset_ns);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s64 rtc_value{};
|
||||
auto res = GetStandardSteadyClockRtcValue(rtc_value);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(rtc_value);
|
||||
}
|
||||
|
||||
void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool is_enabled{};
|
||||
auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push<bool>(is_enabled);
|
||||
}
|
||||
|
||||
void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto automatic_correction{rp.Pop<bool>()};
|
||||
|
||||
auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s32 initial_year{};
|
||||
auto res = GetStandardUserSystemClockInitialYear(initial_year);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(initial_year);
|
||||
}
|
||||
|
||||
void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool is_sufficient{};
|
||||
auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push<bool>(is_sufficient);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Service::PSC::Time::SteadyClockTimePoint time_point{};
|
||||
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx,
|
||||
2 + sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
|
||||
|
||||
s64 time{};
|
||||
auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push<s64>(time);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto type{rp.PopEnum<Service::PSC::Time::TimeType>()};
|
||||
|
||||
Service::PSC::Time::ClockSnapshot snapshot{};
|
||||
auto res = GetClockSnapshot(snapshot, type);
|
||||
|
||||
ctx.WriteBuffer(snapshot);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto clock_type{rp.PopEnum<Service::PSC::Time::TimeType>()};
|
||||
[[maybe_unused]] auto alignment{rp.Pop<u32>()};
|
||||
auto user_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
|
||||
auto network_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
|
||||
|
||||
Service::PSC::Time::ClockSnapshot snapshot{};
|
||||
auto res =
|
||||
GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type);
|
||||
|
||||
ctx.WriteBuffer(snapshot);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Service::PSC::Time::ClockSnapshot a{};
|
||||
Service::PSC::Time::ClockSnapshot b{};
|
||||
|
||||
auto a_buffer{ctx.ReadBuffer(0)};
|
||||
auto b_buffer{ctx.ReadBuffer(1)};
|
||||
|
||||
std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
|
||||
std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
|
||||
|
||||
s64 difference{};
|
||||
auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(difference);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Service::PSC::Time::ClockSnapshot a{};
|
||||
Service::PSC::Time::ClockSnapshot b{};
|
||||
|
||||
auto a_buffer{ctx.ReadBuffer(0)};
|
||||
auto b_buffer{ctx.ReadBuffer(1)};
|
||||
|
||||
std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
|
||||
std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
|
||||
|
||||
s64 time{};
|
||||
auto res = CalculateSpanBetween(time, a, b);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(time);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result StaticService::GetStandardUserSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
|
||||
OutInterface<Service::PSC::Time::SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service));
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardNetworkSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
|
||||
OutInterface<Service::PSC::Time::SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service));
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardSteadyClock(
|
||||
std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service) {
|
||||
OutInterface<Service::PSC::Time::SteadyClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service));
|
||||
}
|
||||
|
||||
Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) {
|
||||
out_service = std::make_shared<TimeZoneService>(m_system, m_file_timestamp_worker,
|
||||
m_setup_info.can_write_timezone_device_location,
|
||||
m_time_zone);
|
||||
Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_service = std::make_shared<TimeZoneService>(
|
||||
m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location,
|
||||
m_time_zone);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardLocalSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
|
||||
OutInterface<Service::PSC::Time::SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service));
|
||||
}
|
||||
|
||||
Result StaticService::GetEphemeralNetworkSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
|
||||
OutInterface<Service::PSC::Time::SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service));
|
||||
}
|
||||
|
||||
Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
|
||||
Result StaticService::GetSharedMemoryNativeHandle(
|
||||
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory));
|
||||
}
|
||||
|
||||
Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
|
||||
LOG_DEBUG(Service_Time, "called. offset_ns={}", offset_ns);
|
||||
|
||||
R_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied);
|
||||
|
||||
R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset(
|
||||
@ -386,62 +154,92 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()));
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardSteadyClockRtcValue(s64& out_rtc_value) {
|
||||
R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(out_rtc_value));
|
||||
Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
|
||||
|
||||
R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value));
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
bool& out_automatic_correction) {
|
||||
Out<bool> out_automatic_correction) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction);
|
||||
});
|
||||
|
||||
R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
out_automatic_correction));
|
||||
}
|
||||
|
||||
Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
bool automatic_correction) {
|
||||
LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
|
||||
|
||||
R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
automatic_correction));
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardUserSystemClockInitialYear(s32& out_year) {
|
||||
out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
|
||||
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); });
|
||||
|
||||
*out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) {
|
||||
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
|
||||
|
||||
R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient));
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
Service::PSC::Time::SteadyClockTimePoint& out_time_point) {
|
||||
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
|
||||
|
||||
R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
out_time_point));
|
||||
}
|
||||
|
||||
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(
|
||||
s64& out_time, Service::PSC::Time::SystemClockContext& context) {
|
||||
Out<s64> out_time, Service::PSC::Time::SystemClockContext& context) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
|
||||
|
||||
R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context));
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot,
|
||||
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot,
|
||||
Service::PSC::Time::TimeType type) {
|
||||
SCOPE_EXIT(
|
||||
{ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
|
||||
|
||||
R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type));
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshotFromSystemClockContext(
|
||||
Service::PSC::Time::ClockSnapshot& out_snapshot,
|
||||
Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,
|
||||
Service::PSC::Time::SystemClockContext& user_context,
|
||||
Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type) {
|
||||
R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(out_snapshot, user_context,
|
||||
network_context, type));
|
||||
Service::PSC::Time::SystemClockContext& network_context) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. type={} out_snapshot={} user_context={} network_context={}", type,
|
||||
*out_snapshot, user_context, network_context);
|
||||
});
|
||||
|
||||
R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(
|
||||
type, out_snapshot, user_context, network_context));
|
||||
}
|
||||
|
||||
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(
|
||||
s64& out_time, Service::PSC::Time::ClockSnapshot& a, Service::PSC::Time::ClockSnapshot& b) {
|
||||
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time,
|
||||
InClockSnapshot a,
|
||||
InClockSnapshot b) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
|
||||
|
||||
R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b));
|
||||
}
|
||||
|
||||
Result StaticService::CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a,
|
||||
Service::PSC::Time::ClockSnapshot& b) {
|
||||
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
|
||||
InClockSnapshot b) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
|
||||
|
||||
R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b));
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/glue/time/manager.h"
|
||||
#include "core/hle/service/glue/time/time_zone.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
@ -29,6 +30,10 @@ class FileTimestampWorker;
|
||||
class StandardSteadyClockResource;
|
||||
|
||||
class StaticService final : public ServiceFramework<StaticService> {
|
||||
using InClockSnapshot = InLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>;
|
||||
using OutClockSnapshot =
|
||||
OutLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>;
|
||||
|
||||
public:
|
||||
explicit StaticService(Core::System& system,
|
||||
Service::PSC::Time::StaticServiceSetupInfo setup_info,
|
||||
@ -36,65 +41,34 @@ public:
|
||||
|
||||
~StaticService() override = default;
|
||||
|
||||
Result GetStandardUserSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
|
||||
Result GetStandardNetworkSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
|
||||
Result GetStandardSteadyClock(std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service);
|
||||
Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service);
|
||||
Result GetStandardLocalSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
|
||||
Result GetStandardUserSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
|
||||
Result GetStandardNetworkSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
|
||||
Result GetStandardSteadyClock(OutInterface<Service::PSC::Time::SteadyClock> out_service);
|
||||
Result GetTimeZoneService(OutInterface<TimeZoneService> out_service);
|
||||
Result GetStandardLocalSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
|
||||
Result GetEphemeralNetworkSystemClock(
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
|
||||
Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory);
|
||||
Result SetStandardSteadyClockInternalOffset(s64 offset);
|
||||
Result GetStandardSteadyClockRtcValue(s64& out_rtc_value);
|
||||
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_automatic_correction);
|
||||
OutInterface<Service::PSC::Time::SystemClock> out_service);
|
||||
Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
|
||||
Result SetStandardSteadyClockInternalOffset(s64 offset_ns);
|
||||
Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
|
||||
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
|
||||
Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
|
||||
Result GetStandardUserSystemClockInitialYear(s32& out_year);
|
||||
Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient);
|
||||
Result GetStandardUserSystemClockInitialYear(Out<s32> out_year);
|
||||
Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
|
||||
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
Service::PSC::Time::SteadyClockTimePoint& out_time_point);
|
||||
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
|
||||
Result CalculateMonotonicSystemClockBaseTimePoint(
|
||||
s64& out_time, Service::PSC::Time::SystemClockContext& context);
|
||||
Result GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot,
|
||||
Service::PSC::Time::TimeType type);
|
||||
Out<s64> out_time, Service::PSC::Time::SystemClockContext& context);
|
||||
Result GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type);
|
||||
Result GetClockSnapshotFromSystemClockContext(
|
||||
Service::PSC::Time::ClockSnapshot& out_snapshot,
|
||||
Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,
|
||||
Service::PSC::Time::SystemClockContext& user_context,
|
||||
Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type);
|
||||
Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time,
|
||||
Service::PSC::Time::ClockSnapshot& a,
|
||||
Service::PSC::Time::ClockSnapshot& b);
|
||||
Result CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a,
|
||||
Service::PSC::Time::ClockSnapshot& b);
|
||||
Service::PSC::Time::SystemClockContext& network_context);
|
||||
Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
|
||||
InClockSnapshot a, InClockSnapshot b);
|
||||
Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b);
|
||||
|
||||
private:
|
||||
Result GetClockSnapshotImpl(Service::PSC::Time::ClockSnapshot& out_snapshot,
|
||||
Service::PSC::Time::SystemClockContext& user_context,
|
||||
Service::PSC::Time::SystemClockContext& network_context,
|
||||
Service::PSC::Time::TimeType type);
|
||||
|
||||
void Handle_GetStandardUserSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetStandardSteadyClock(HLERequestContext& ctx);
|
||||
void Handle_GetTimeZoneService(HLERequestContext& ctx);
|
||||
void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx);
|
||||
void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx);
|
||||
void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx);
|
||||
void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
|
||||
void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx);
|
||||
void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
|
||||
void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
|
||||
void Handle_GetClockSnapshot(HLERequestContext& ctx);
|
||||
void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
|
||||
void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
|
||||
void Handle_CalculateSpanBetween(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/glue/time/file_timestamp_worker.h"
|
||||
#include "core/hle/service/glue/time/time_zone.h"
|
||||
#include "core/hle/service/glue/time/time_zone_binary.h"
|
||||
@ -28,20 +30,20 @@ TimeZoneService::TimeZoneService(
|
||||
m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"},
|
||||
{1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"},
|
||||
{2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"},
|
||||
{3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"},
|
||||
{4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"},
|
||||
{5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
|
||||
{6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"},
|
||||
{8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"},
|
||||
{20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"},
|
||||
{100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"},
|
||||
{101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
||||
{201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"},
|
||||
{202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
|
||||
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
||||
{1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"},
|
||||
{2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"},
|
||||
{3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"},
|
||||
{4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"},
|
||||
{5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"},
|
||||
{6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"},
|
||||
{8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"},
|
||||
{20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"},
|
||||
{100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"},
|
||||
{101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"},
|
||||
{201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"},
|
||||
{202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
@ -53,220 +55,16 @@ TimeZoneService::TimeZoneService(
|
||||
|
||||
TimeZoneService::~TimeZoneService() = default;
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetDeviceLocationName(
|
||||
Out<Service::PSC::Time::LocationName> out_location_name) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
|
||||
|
||||
Service::PSC::Time::LocationName name{};
|
||||
auto res = GetDeviceLocationName(name);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<Service::PSC::Time::LocationName>(name);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
|
||||
|
||||
auto res = SetDeviceLocation(name);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
u32 count{};
|
||||
auto res = GetTotalLocationNameCount(count);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto index{rp.Pop<u32>()};
|
||||
|
||||
auto max_names{ctx.GetWriteBufferSize() / sizeof(Service::PSC::Time::LocationName)};
|
||||
|
||||
std::vector<Service::PSC::Time::LocationName> names{};
|
||||
u32 count{};
|
||||
auto res = LoadLocationNameList(count, names, max_names, index);
|
||||
|
||||
ctx.WriteBuffer(names);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
|
||||
|
||||
Tz::Rule rule{};
|
||||
auto res = LoadTimeZoneRule(rule, name);
|
||||
|
||||
ctx.WriteBuffer(rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Service::PSC::Time::RuleVersion rule_version{};
|
||||
auto res = GetTimeZoneRuleVersion(rule_version);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::RuleVersion) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<Service::PSC::Time::RuleVersion>(rule_version);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Service::PSC::Time::LocationName name{};
|
||||
Service::PSC::Time::SteadyClockTimePoint time_point{};
|
||||
auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx,
|
||||
2 + (sizeof(Service::PSC::Time::LocationName) / sizeof(u32)) +
|
||||
(sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<Service::PSC::Time::LocationName>(name);
|
||||
rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
auto res = SetDeviceLocationNameWithTimeZoneRule();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(Service::PSC::Time::ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetDeviceLocationNameOperationEventReadableHandle(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
auto rule_buffer{ctx.ReadBuffer()};
|
||||
Tz::Rule rule{};
|
||||
std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule));
|
||||
|
||||
Service::PSC::Time::CalendarTime calendar_time{};
|
||||
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
|
||||
auto res = ToCalendarTime(calendar_time, additional_info, time, rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx,
|
||||
2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) +
|
||||
(sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time);
|
||||
rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
LOG_DEBUG(Service_Time, "called. time={}", time);
|
||||
|
||||
Service::PSC::Time::CalendarTime calendar_time{};
|
||||
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
|
||||
auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx,
|
||||
2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) +
|
||||
(sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time);
|
||||
rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()};
|
||||
|
||||
LOG_DEBUG(Service_Time, "called. calendar year {} month {} day {} hour {} minute {} second {}",
|
||||
calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute,
|
||||
calendar.second);
|
||||
|
||||
auto binary{ctx.ReadBuffer()};
|
||||
|
||||
Tz::Rule rule{};
|
||||
std::memcpy(&rule, binary.data(), sizeof(Tz::Rule));
|
||||
|
||||
u32 count{};
|
||||
std::array<s64, 2> times{};
|
||||
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
|
||||
|
||||
auto res = ToPosixTime(count, times, times_count, calendar, rule);
|
||||
|
||||
ctx.WriteBuffer(times);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()};
|
||||
|
||||
u32 count{};
|
||||
std::array<s64, 2> times{};
|
||||
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
|
||||
|
||||
auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar);
|
||||
|
||||
ctx.WriteBuffer(times);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result TimeZoneService::GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name) {
|
||||
R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name));
|
||||
}
|
||||
|
||||
Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& location_name) {
|
||||
Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName& location_name) {
|
||||
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
|
||||
|
||||
R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
|
||||
R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound);
|
||||
|
||||
@ -282,7 +80,7 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca
|
||||
|
||||
Service::PSC::Time::SteadyClockTimePoint time_point{};
|
||||
Service::PSC::Time::LocationName name{};
|
||||
R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(time_point, name));
|
||||
R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(&name, &time_point));
|
||||
|
||||
m_set_sys->SetDeviceTimeZoneLocationName(name);
|
||||
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point);
|
||||
@ -294,19 +92,27 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) {
|
||||
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
|
||||
|
||||
R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count));
|
||||
}
|
||||
|
||||
Result TimeZoneService::LoadLocationNameList(
|
||||
u32& out_count, std::vector<Service::PSC::Time::LocationName>& out_names, size_t max_names,
|
||||
u32 index) {
|
||||
Out<u32> out_count,
|
||||
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}",
|
||||
index, *out_count, out_names[0], out_names[1]);
|
||||
});
|
||||
|
||||
std::scoped_lock l{m_mutex};
|
||||
R_RETURN(GetTimeZoneLocationList(out_count, out_names, max_names, index));
|
||||
R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index));
|
||||
}
|
||||
|
||||
Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule,
|
||||
Service::PSC::Time::LocationName& name) {
|
||||
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& name) {
|
||||
LOG_DEBUG(Service_Time, "called. name={}", name);
|
||||
|
||||
std::scoped_lock l{m_mutex};
|
||||
std::span<const u8> binary{};
|
||||
size_t binary_size{};
|
||||
@ -314,23 +120,43 @@ Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule,
|
||||
R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version) {
|
||||
Result TimeZoneService::GetTimeZoneRuleVersion(
|
||||
Out<Service::PSC::Time::RuleVersion> out_rule_version) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
|
||||
|
||||
R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
|
||||
Service::PSC::Time::SteadyClockTimePoint& out_time_point,
|
||||
Service::PSC::Time::LocationName& location_name) {
|
||||
R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(out_time_point, location_name));
|
||||
Out<Service::PSC::Time::LocationName> location_name,
|
||||
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name,
|
||||
*out_time_point);
|
||||
});
|
||||
|
||||
R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point));
|
||||
}
|
||||
|
||||
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule() {
|
||||
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
|
||||
Service::PSC::Time::LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) {
|
||||
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
|
||||
|
||||
R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
|
||||
R_RETURN(Service::PSC::Time::ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> binary) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(Service::PSC::Time::ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
|
||||
Kernel::KEvent** out_event) {
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
if (!operation_event_initialized) {
|
||||
operation_event_initialized = false;
|
||||
|
||||
@ -342,36 +168,56 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
|
||||
g_list_nodes.push_back(m_operation_event);
|
||||
}
|
||||
|
||||
*out_event = m_operation_event.m_event;
|
||||
*out_event = &m_operation_event.m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTime(
|
||||
Service::PSC::Time::CalendarTime& out_calendar_time,
|
||||
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule) {
|
||||
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
|
||||
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
|
||||
*out_calendar_time, *out_additional_info);
|
||||
});
|
||||
|
||||
R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTimeWithMyRule(
|
||||
Service::PSC::Time::CalendarTime& out_calendar_time,
|
||||
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time) {
|
||||
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
|
||||
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
|
||||
*out_calendar_time, *out_additional_info);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times,
|
||||
u32 out_times_count,
|
||||
Service::PSC::Time::CalendarTime& calendar_time,
|
||||
Tz::Rule& rule) {
|
||||
R_RETURN(
|
||||
m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
|
||||
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const Service::PSC::Time::CalendarTime& calendar_time,
|
||||
InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
|
||||
u32 out_times_count,
|
||||
Service::PSC::Time::CalendarTime& calendar_time) {
|
||||
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count,
|
||||
calendar_time));
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(
|
||||
Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const Service::PSC::Time::CalendarTime& calendar_time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time));
|
||||
}
|
||||
|
||||
} // namespace Service::Glue::Time
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
@ -33,6 +34,9 @@ namespace Service::Glue::Time {
|
||||
class FileTimestampWorker;
|
||||
|
||||
class TimeZoneService final : public ServiceFramework<TimeZoneService> {
|
||||
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
||||
using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
||||
|
||||
public:
|
||||
explicit TimeZoneService(
|
||||
Core::System& system, FileTimestampWorker& file_timestamp_worker,
|
||||
@ -41,46 +45,35 @@ public:
|
||||
|
||||
~TimeZoneService() override;
|
||||
|
||||
Result GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name);
|
||||
Result SetDeviceLocation(Service::PSC::Time::LocationName& location_name);
|
||||
Result GetTotalLocationNameCount(u32& out_count);
|
||||
Result LoadLocationNameList(u32& out_count,
|
||||
std::vector<Service::PSC::Time::LocationName>& out_names,
|
||||
size_t max_names, u32 index);
|
||||
Result LoadTimeZoneRule(Tz::Rule& out_rule, Service::PSC::Time::LocationName& name);
|
||||
Result GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version);
|
||||
Result GetDeviceLocationName(Out<Service::PSC::Time::LocationName> out_location_name);
|
||||
Result SetDeviceLocationName(Service::PSC::Time::LocationName& location_name);
|
||||
Result GetTotalLocationNameCount(Out<u32> out_count);
|
||||
Result LoadLocationNameList(
|
||||
Out<u32> out_count,
|
||||
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index);
|
||||
Result LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& location_name);
|
||||
Result GetTimeZoneRuleVersion(Out<Service::PSC::Time::RuleVersion> out_rule_version);
|
||||
Result GetDeviceLocationNameAndUpdatedTime(
|
||||
Service::PSC::Time::SteadyClockTimePoint& out_time_point,
|
||||
Service::PSC::Time::LocationName& location_name);
|
||||
Result SetDeviceLocationNameWithTimeZoneRule();
|
||||
Result GetDeviceLocationNameOperationEventReadableHandle(Kernel::KEvent** out_event);
|
||||
Result ToCalendarTime(Service::PSC::Time::CalendarTime& out_calendar_time,
|
||||
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule);
|
||||
Result ToCalendarTimeWithMyRule(Service::PSC::Time::CalendarTime& out_calendar_time,
|
||||
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info,
|
||||
s64 time);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
Service::PSC::Time::CalendarTime& calendar_time, Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
Service::PSC::Time::CalendarTime& calendar_time);
|
||||
Out<Service::PSC::Time::LocationName> location_name,
|
||||
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
|
||||
Result SetDeviceLocationNameWithTimeZoneRule(Service::PSC::Time::LocationName& location_name,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> binary);
|
||||
Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary);
|
||||
Result GetDeviceLocationNameOperationEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result ToCalendarTime(Out<Service::PSC::Time::CalendarTime> out_calendar_time,
|
||||
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info,
|
||||
s64 time, InRule rule);
|
||||
Result ToCalendarTimeWithMyRule(
|
||||
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
|
||||
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time);
|
||||
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const Service::PSC::Time::CalendarTime& calendar_time, InRule rule);
|
||||
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const Service::PSC::Time::CalendarTime& calendar_time);
|
||||
|
||||
private:
|
||||
void Handle_GetDeviceLocationName(HLERequestContext& ctx);
|
||||
void Handle_SetDeviceLocationName(HLERequestContext& ctx);
|
||||
void Handle_GetTotalLocationNameCount(HLERequestContext& ctx);
|
||||
void Handle_LoadLocationNameList(HLERequestContext& ctx);
|
||||
void Handle_LoadTimeZoneRule(HLERequestContext& ctx);
|
||||
void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx);
|
||||
void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx);
|
||||
void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx);
|
||||
void Handle_ParseTimeZoneBinary(HLERequestContext& ctx);
|
||||
void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx);
|
||||
void Handle_ToCalendarTime(HLERequestContext& ctx);
|
||||
void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx);
|
||||
void Handle_ToPosixTime(HLERequestContext& ctx);
|
||||
void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||
|
||||
|
@ -103,7 +103,7 @@ void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName
|
||||
return;
|
||||
}
|
||||
// out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name);
|
||||
out_path = fmt::format("/zoneinfo/{}", name.name.data());
|
||||
out_path = fmt::format("/zoneinfo/{}", name.data());
|
||||
}
|
||||
|
||||
bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) {
|
||||
@ -169,7 +169,7 @@ Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
|
||||
}
|
||||
|
||||
Result GetTimeZoneLocationList(u32& out_count,
|
||||
std::vector<Service::PSC::Time::LocationName>& out_names,
|
||||
std::span<Service::PSC::Time::LocationName> out_names,
|
||||
size_t max_names, u32 index) {
|
||||
std::string path{};
|
||||
GetTimeZoneBinaryListPath(path);
|
||||
@ -193,7 +193,7 @@ Result GetTimeZoneLocationList(u32& out_count,
|
||||
|
||||
if (chr == '\n') {
|
||||
if (name_count >= index) {
|
||||
out_names.push_back(current_name);
|
||||
out_names[out_count] = current_name;
|
||||
out_count++;
|
||||
if (out_count >= max_names) {
|
||||
break;
|
||||
@ -209,10 +209,9 @@ Result GetTimeZoneLocationList(u32& out_count,
|
||||
break;
|
||||
}
|
||||
|
||||
R_UNLESS(current_name_len <= current_name.name.size() - 2,
|
||||
Service::PSC::Time::ResultFailed);
|
||||
R_UNLESS(current_name_len <= current_name.size() - 2, Service::PSC::Time::ResultFailed);
|
||||
|
||||
current_name.name[current_name_len++] = chr;
|
||||
current_name[current_name_len++] = chr;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
|
@ -26,7 +26,7 @@ Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version);
|
||||
Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
|
||||
Service::PSC::Time::LocationName& name);
|
||||
Result GetTimeZoneLocationList(u32& out_count,
|
||||
std::vector<Service::PSC::Time::LocationName>& out_names,
|
||||
std::span<Service::PSC::Time::LocationName> out_names,
|
||||
size_t max_names, u32 index);
|
||||
|
||||
} // namespace Service::Glue::Time
|
||||
|
@ -38,11 +38,12 @@ T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set
|
||||
|
||||
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
|
||||
FileTimestampWorker& file_timestamp_worker)
|
||||
: m_system{system}, m_ctx{m_system, "Glue:58"}, m_event{m_ctx.CreateEvent("Glue:58:Event")},
|
||||
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent(
|
||||
"Glue:TimeWorker:Event")},
|
||||
m_steady_clock_resource{steady_clock_resource},
|
||||
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent(
|
||||
"Glue:58:SteadyClockTimerEvent")},
|
||||
m_timer_file_system{m_ctx.CreateEvent("Glue:58:FileTimeTimerEvent")},
|
||||
"Glue:TimeWorker:SteadyClockTimerEvent")},
|
||||
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
|
||||
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
|
||||
g_ig_report_network_clock_context_set = false;
|
||||
g_report_network_clock_context = {};
|
||||
@ -113,17 +114,17 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t
|
||||
std::chrono::nanoseconds(fs_notify_time_ns),
|
||||
m_timer_file_system_timing_event);
|
||||
|
||||
auto res = m_time_sm->GetStandardLocalSystemClock(m_local_clock);
|
||||
auto res = m_time_sm->GetStandardLocalSystemClock(&m_local_clock);
|
||||
ASSERT(res == ResultSuccess);
|
||||
res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
res = m_time_sm->GetStandardNetworkSystemClock(m_network_clock);
|
||||
res = m_time_sm->GetStandardNetworkSystemClock(&m_network_clock);
|
||||
ASSERT(res == ResultSuccess);
|
||||
res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
res = m_time_sm->GetEphemeralNetworkSystemClock(m_ephemeral_clock);
|
||||
res = m_time_sm->GetEphemeralNetworkSystemClock(&m_ephemeral_clock);
|
||||
ASSERT(res == ResultSuccess);
|
||||
res =
|
||||
m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event);
|
||||
@ -183,22 +184,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
||||
AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
|
||||
// TODO
|
||||
// AddWaiter(gIPmModuleService::GetEvent(), 1);
|
||||
AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange);
|
||||
AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange);
|
||||
} else {
|
||||
AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
|
||||
// TODO
|
||||
// AddWaiter(gIPmModuleService::GetEvent(), 1);
|
||||
AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange);
|
||||
AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange);
|
||||
AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms);
|
||||
AddWaiter(&m_local_clock_event->GetReadableEvent(), EventType::UpdateLocalSystemClock);
|
||||
AddWaiter(&m_network_clock_event->GetReadableEvent(),
|
||||
EventType::UpdateNetworkSystemClock);
|
||||
AddWaiter(&m_ephemeral_clock_event->GetReadableEvent(),
|
||||
EventType::UpdateEphemeralSystemClock);
|
||||
AddWaiter(m_local_clock_event, EventType::UpdateLocalSystemClock);
|
||||
AddWaiter(m_network_clock_event, EventType::UpdateNetworkSystemClock);
|
||||
AddWaiter(m_ephemeral_clock_event, EventType::UpdateEphemeralSystemClock);
|
||||
AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock);
|
||||
AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp);
|
||||
AddWaiter(&m_standard_user_auto_correct_clock_event->GetReadableEvent(),
|
||||
EventType::AutoCorrect);
|
||||
AddWaiter(m_standard_user_auto_correct_clock_event, EventType::AutoCorrect);
|
||||
}
|
||||
|
||||
s32 out_index{-1};
|
||||
@ -237,7 +235,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
||||
m_local_clock_event->Clear();
|
||||
|
||||
Service::PSC::Time::SystemClockContext context{};
|
||||
auto res = m_local_clock->GetSystemClockContext(context);
|
||||
auto res = m_local_clock->GetSystemClockContext(&context);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
m_set_sys->SetUserSystemClockContext(context);
|
||||
@ -248,12 +246,12 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
||||
case EventType::UpdateNetworkSystemClock: {
|
||||
m_network_clock_event->Clear();
|
||||
Service::PSC::Time::SystemClockContext context{};
|
||||
auto res = m_network_clock->GetSystemClockContext(context);
|
||||
auto res = m_network_clock->GetSystemClockContext(&context);
|
||||
ASSERT(res == ResultSuccess);
|
||||
m_set_sys->SetNetworkSystemClockContext(context);
|
||||
|
||||
s64 time{};
|
||||
if (m_network_clock->GetCurrentTime(time) != ResultSuccess) {
|
||||
if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -275,13 +273,13 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
||||
m_ephemeral_clock_event->Clear();
|
||||
|
||||
Service::PSC::Time::SystemClockContext context{};
|
||||
auto res = m_ephemeral_clock->GetSystemClockContext(context);
|
||||
auto res = m_ephemeral_clock->GetSystemClockContext(&context);
|
||||
if (res != ResultSuccess) {
|
||||
break;
|
||||
}
|
||||
|
||||
s64 time{};
|
||||
res = m_ephemeral_clock->GetCurrentTime(time);
|
||||
res = m_ephemeral_clock->GetCurrentTime(&time);
|
||||
if (res != ResultSuccess) {
|
||||
break;
|
||||
}
|
||||
@ -317,11 +315,11 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
||||
|
||||
bool automatic_correction{};
|
||||
auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
automatic_correction);
|
||||
&automatic_correction);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
Service::PSC::Time::SteadyClockTimePoint time_point{};
|
||||
res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
|
||||
res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point);
|
||||
ASSERT(res == ResultSuccess);
|
||||
|
||||
m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
|
||||
|
@ -49,10 +49,10 @@ private:
|
||||
std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock;
|
||||
StandardSteadyClockResource& m_steady_clock_resource;
|
||||
FileTimestampWorker& m_file_timestamp_worker;
|
||||
Kernel::KEvent* m_local_clock_event{};
|
||||
Kernel::KEvent* m_network_clock_event{};
|
||||
Kernel::KEvent* m_ephemeral_clock_event{};
|
||||
Kernel::KEvent* m_standard_user_auto_correct_clock_event{};
|
||||
Kernel::KReadableEvent* m_local_clock_event{};
|
||||
Kernel::KReadableEvent* m_network_clock_event{};
|
||||
Kernel::KReadableEvent* m_ephemeral_clock_event{};
|
||||
Kernel::KReadableEvent* m_standard_user_auto_correct_clock_event{};
|
||||
Kernel::KEvent* m_timer_steady_clock{};
|
||||
std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event;
|
||||
Kernel::KEvent* m_timer_file_system{};
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/hid/hid_server.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/memory.h"
|
||||
@ -153,7 +154,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r
|
||||
{104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
|
||||
{106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
|
||||
{107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
|
||||
{108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"},
|
||||
{108, C<&IHidServer::GetPlayerLedPattern>, "GetPlayerLedPattern"},
|
||||
{109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
|
||||
{120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
|
||||
{121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
|
||||
@ -1136,19 +1137,39 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
|
||||
|
||||
Core::HID::LedPattern pattern{0, 0, 0, 0};
|
||||
auto controller = GetResourceManager()->GetNpad();
|
||||
const auto result = controller->GetLedPattern(npad_id, pattern);
|
||||
|
||||
Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
||||
Core::HID::NpadIdType npad_id) {
|
||||
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(result);
|
||||
rb.Push(pattern.raw);
|
||||
switch (npad_id) {
|
||||
case Core::HID::NpadIdType::Player1:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player2:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 0, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player3:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player4:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 1};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player5:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 1};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player6:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player7:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 1};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player8:
|
||||
*out_led_pattern = Core::HID::LedPattern{0, 1, 1, 0};
|
||||
R_SUCCEED();
|
||||
default:
|
||||
*out_led_pattern = Core::HID::LedPattern{0, 0, 0, 0};
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "hid_core/hid_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
@ -66,7 +68,8 @@ private:
|
||||
void DeactivateNpad(HLERequestContext& ctx);
|
||||
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
||||
void DisconnectNpad(HLERequestContext& ctx);
|
||||
void GetPlayerLedPattern(HLERequestContext& ctx);
|
||||
Result GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
||||
Core::HID::NpadIdType npad_id);
|
||||
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
||||
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
||||
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
||||
|
@ -111,7 +111,8 @@ private:
|
||||
R_RETURN(result);
|
||||
}
|
||||
|
||||
Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) {
|
||||
Result UpdateLatest(Out<CharInfo> out_char_info, const CharInfo& char_info,
|
||||
SourceFlag source_flag) {
|
||||
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
|
||||
|
||||
R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag));
|
||||
@ -159,7 +160,7 @@ private:
|
||||
R_RETURN(result);
|
||||
}
|
||||
|
||||
Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data,
|
||||
Result UpdateLatest1(Out<StoreData> out_store_data, const StoreData& store_data,
|
||||
SourceFlag source_flag) {
|
||||
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
|
||||
R_UNLESS(is_system, ResultPermissionDenied);
|
||||
@ -243,7 +244,7 @@ private:
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GetIndex(Out<s32> out_index, CharInfo& char_info) {
|
||||
Result GetIndex(Out<s32> out_index, const CharInfo& char_info) {
|
||||
LOG_DEBUG(Service_Mii, "called");
|
||||
|
||||
R_RETURN(manager->GetIndex(metadata, char_info, *out_index));
|
||||
@ -257,25 +258,25 @@ private:
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) {
|
||||
Result Convert(Out<CharInfo> out_char_info, const Ver3StoreData& mii_v3) {
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3));
|
||||
}
|
||||
|
||||
Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) {
|
||||
Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, const CoreData& core_data) {
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data));
|
||||
}
|
||||
|
||||
Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) {
|
||||
Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, const CharInfo& char_info) {
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info));
|
||||
}
|
||||
|
||||
Result Append(CharInfo& char_info) {
|
||||
Result Append(const CharInfo& char_info) {
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
R_RETURN(manager->Append(metadata, char_info));
|
||||
|
@ -1405,7 +1405,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
|
||||
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
|
||||
|
||||
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{};
|
||||
static_service->GetTimeZoneService(timezone_service);
|
||||
static_service->GetTimeZoneService(&timezone_service);
|
||||
|
||||
Service::PSC::Time::CalendarTime calendar_time{};
|
||||
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
|
||||
@ -1416,7 +1416,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
|
||||
amiibo_date.SetMonth(1);
|
||||
amiibo_date.SetDay(1);
|
||||
|
||||
if (timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time) ==
|
||||
if (timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time) ==
|
||||
ResultSuccess) {
|
||||
amiibo_date.SetYear(calendar_time.year);
|
||||
amiibo_date.SetMonth(calendar_time.month);
|
||||
@ -1431,10 +1431,10 @@ s64 NfcDevice::GetCurrentPosixTime() const {
|
||||
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
|
||||
static_service->GetStandardSteadyClock(steady_clock);
|
||||
static_service->GetStandardSteadyClock(&steady_clock);
|
||||
|
||||
Service::PSC::Time::SteadyClockTimePoint time_point{};
|
||||
R_ASSERT(steady_clock->GetCurrentTimePoint(time_point));
|
||||
R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
|
||||
return time_point.time_point;
|
||||
}
|
||||
|
||||
|
@ -91,10 +91,10 @@ Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max
|
||||
true);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
|
||||
static_service->GetStandardSteadyClock(steady_clock);
|
||||
static_service->GetStandardSteadyClock(&steady_clock);
|
||||
|
||||
Service::PSC::Time::SteadyClockTimePoint time_point{};
|
||||
R_ASSERT(steady_clock->GetCurrentTimePoint(time_point));
|
||||
R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
|
||||
|
||||
const s64 elapsed_time = time_point.time_point - time_since_last_error;
|
||||
if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) {
|
||||
@ -754,10 +754,10 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
|
||||
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
|
||||
|
||||
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
|
||||
static_service->GetStandardSteadyClock(steady_clock);
|
||||
static_service->GetStandardSteadyClock(&steady_clock);
|
||||
|
||||
Service::PSC::Time::SteadyClockTimePoint time_point{};
|
||||
R_ASSERT(steady_clock->GetCurrentTimePoint(time_point));
|
||||
R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
|
||||
|
||||
time_since_last_error = time_point.time_point;
|
||||
}
|
||||
|
@ -83,7 +83,9 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
|
||||
|
||||
// Check if this memory block is heap.
|
||||
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
|
||||
if (svc_mem_info.size > region_size) {
|
||||
if (region_start + region_size == svc_mem_info.base_address) {
|
||||
region_size += svc_mem_info.size;
|
||||
} else if (svc_mem_info.size > region_size) {
|
||||
region_size = svc_mem_info.size;
|
||||
region_start = svc_mem_info.base_address;
|
||||
}
|
||||
|
@ -67,10 +67,7 @@ public:
|
||||
const SyncpointManager& GetSyncpointManager() const;
|
||||
|
||||
struct Host1xDeviceFileData {
|
||||
std::unordered_map<DeviceFD, u32> fd_to_id{};
|
||||
std::deque<u32> syncpts_accumulated{};
|
||||
u32 nvdec_next_id{};
|
||||
u32 vic_next_id{};
|
||||
};
|
||||
|
||||
Host1xDeviceFileData& Host1xDeviceFile();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "core/hle/service/nvdrv/core/container.h"
|
||||
#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
|
||||
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
|
||||
#include "video_core/host1x/host1x.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
|
||||
namespace Service::Nvidia::Devices {
|
||||
@ -21,13 +22,8 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
|
||||
switch (command.group) {
|
||||
case 0x0:
|
||||
switch (command.cmd) {
|
||||
case 0x1: {
|
||||
auto& host1x_file = core.Host1xDeviceFile();
|
||||
if (!host1x_file.fd_to_id.contains(fd)) {
|
||||
host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++;
|
||||
}
|
||||
case 0x1:
|
||||
return WrapFixedVariable(this, &nvhost_nvdec::Submit, input, output, fd);
|
||||
}
|
||||
case 0x2:
|
||||
return WrapFixed(this, &nvhost_nvdec::GetSyncpoint, input, output);
|
||||
case 0x3:
|
||||
@ -72,15 +68,12 @@ void nvhost_nvdec::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
|
||||
LOG_INFO(Service_NVDRV, "NVDEC video stream started");
|
||||
system.SetNVDECActive(true);
|
||||
sessions[fd] = session_id;
|
||||
host1x.StartDevice(fd, Tegra::Host1x::ChannelType::NvDec, channel_syncpoint);
|
||||
}
|
||||
|
||||
void nvhost_nvdec::OnClose(DeviceFD fd) {
|
||||
LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
|
||||
auto& host1x_file = core.Host1xDeviceFile();
|
||||
const auto iter = host1x_file.fd_to_id.find(fd);
|
||||
if (iter != host1x_file.fd_to_id.end()) {
|
||||
system.GPU().ClearCdmaInstance(iter->second);
|
||||
}
|
||||
host1x.StopDevice(fd, Tegra::Host1x::ChannelType::NvDec);
|
||||
system.SetNVDECActive(false);
|
||||
auto it = sessions.find(fd);
|
||||
if (it != sessions.end()) {
|
||||
|
@ -55,8 +55,9 @@ std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size
|
||||
|
||||
nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, NvCore::Container& core_,
|
||||
NvCore::ChannelType channel_type_)
|
||||
: nvdevice{system_}, core{core_}, syncpoint_manager{core.GetSyncpointManager()},
|
||||
nvmap{core.GetNvMapFile()}, channel_type{channel_type_} {
|
||||
: nvdevice{system_}, host1x{system_.Host1x()}, core{core_},
|
||||
syncpoint_manager{core.GetSyncpointManager()}, nvmap{core.GetNvMapFile()},
|
||||
channel_type{channel_type_} {
|
||||
auto& syncpts_accumulated = core.Host1xDeviceFile().syncpts_accumulated;
|
||||
if (syncpts_accumulated.empty()) {
|
||||
channel_syncpoint = syncpoint_manager.AllocateSyncpoint(false);
|
||||
@ -95,24 +96,24 @@ NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, De
|
||||
offset += SliceVectors(data, syncpt_increments, params.syncpoint_count, offset);
|
||||
offset += SliceVectors(data, fence_thresholds, params.fence_count, offset);
|
||||
|
||||
auto& gpu = system.GPU();
|
||||
auto* session = core.GetSession(sessions[fd]);
|
||||
|
||||
if (gpu.UseNvdec()) {
|
||||
for (std::size_t i = 0; i < syncpt_increments.size(); i++) {
|
||||
const SyncptIncr& syncpt_incr = syncpt_increments[i];
|
||||
fence_thresholds[i] =
|
||||
syncpoint_manager.IncrementSyncpointMaxExt(syncpt_incr.id, syncpt_incr.increments);
|
||||
}
|
||||
for (std::size_t i = 0; i < syncpt_increments.size(); i++) {
|
||||
const SyncptIncr& syncpt_incr = syncpt_increments[i];
|
||||
fence_thresholds[i] =
|
||||
syncpoint_manager.IncrementSyncpointMaxExt(syncpt_incr.id, syncpt_incr.increments);
|
||||
}
|
||||
|
||||
for (const auto& cmd_buffer : command_buffers) {
|
||||
const auto object = nvmap.GetHandle(cmd_buffer.memory_id);
|
||||
ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
|
||||
Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
|
||||
session->process->GetMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(),
|
||||
cmdlist.size() * sizeof(u32));
|
||||
gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
|
||||
Core::Memory::CpuGuestMemory<Tegra::ChCommandHeader,
|
||||
Core::Memory::GuestMemoryFlags::SafeRead>
|
||||
cmdlist(session->process->GetMemory(), object->address + cmd_buffer.offset,
|
||||
cmd_buffer.word_count);
|
||||
host1x.PushEntries(fd, std::move(cmdlist));
|
||||
}
|
||||
|
||||
// Some games expect command_buffers to be written back
|
||||
offset = 0;
|
||||
offset += WriteVectors(data, command_buffers, offset);
|
||||
|
@ -119,6 +119,7 @@ protected:
|
||||
|
||||
Kernel::KEvent* QueryEvent(u32 event_id) override;
|
||||
|
||||
Tegra::Host1x::Host1x& host1x;
|
||||
u32 channel_syncpoint;
|
||||
s32_le nvmap_fd{};
|
||||
u32_le submit_timeout{};
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "core/hle/service/nvdrv/core/container.h"
|
||||
#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
|
||||
#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
|
||||
#include "video_core/host1x/host1x.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
|
||||
namespace Service::Nvidia::Devices {
|
||||
@ -21,13 +22,8 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
|
||||
switch (command.group) {
|
||||
case 0x0:
|
||||
switch (command.cmd) {
|
||||
case 0x1: {
|
||||
auto& host1x_file = core.Host1xDeviceFile();
|
||||
if (!host1x_file.fd_to_id.contains(fd)) {
|
||||
host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++;
|
||||
}
|
||||
case 0x1:
|
||||
return WrapFixedVariable(this, &nvhost_vic::Submit, input, output, fd);
|
||||
}
|
||||
case 0x2:
|
||||
return WrapFixed(this, &nvhost_vic::GetSyncpoint, input, output);
|
||||
case 0x3:
|
||||
@ -70,14 +66,11 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
|
||||
|
||||
void nvhost_vic::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
|
||||
sessions[fd] = session_id;
|
||||
host1x.StartDevice(fd, Tegra::Host1x::ChannelType::VIC, channel_syncpoint);
|
||||
}
|
||||
|
||||
void nvhost_vic::OnClose(DeviceFD fd) {
|
||||
auto& host1x_file = core.Host1xDeviceFile();
|
||||
const auto iter = host1x_file.fd_to_id.find(fd);
|
||||
if (iter != host1x_file.fd_to_id.end()) {
|
||||
system.GPU().ClearCdmaInstance(iter->second);
|
||||
}
|
||||
host1x.StopDevice(fd, Tegra::Host1x::ChannelType::VIC);
|
||||
sessions.erase(fd);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/intrusive_list.h"
|
||||
@ -21,8 +22,14 @@ class System;
|
||||
namespace Service::PSC::Time {
|
||||
using ClockSourceId = Common::UUID;
|
||||
|
||||
enum class TimeType : u8 {
|
||||
UserSystemClock = 0,
|
||||
NetworkSystemClock = 1,
|
||||
LocalSystemClock = 2,
|
||||
};
|
||||
|
||||
struct SteadyClockTimePoint {
|
||||
constexpr bool IdMatches(SteadyClockTimePoint& other) {
|
||||
constexpr bool IdMatches(const SteadyClockTimePoint& other) const {
|
||||
return clock_source_id == other.clock_source_id;
|
||||
}
|
||||
bool operator==(const SteadyClockTimePoint& other) const = default;
|
||||
@ -42,12 +49,6 @@ struct SystemClockContext {
|
||||
static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!");
|
||||
static_assert(std::is_trivial_v<SystemClockContext>);
|
||||
|
||||
enum class TimeType : u8 {
|
||||
UserSystemClock,
|
||||
NetworkSystemClock,
|
||||
LocalSystemClock,
|
||||
};
|
||||
|
||||
struct CalendarTime {
|
||||
s16 year;
|
||||
s8 month;
|
||||
@ -67,14 +68,10 @@ struct CalendarAdditionalInfo {
|
||||
};
|
||||
static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!");
|
||||
|
||||
struct LocationName {
|
||||
std::array<char, 36> name;
|
||||
};
|
||||
using LocationName = std::array<char, 0x24>;
|
||||
static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!");
|
||||
|
||||
struct RuleVersion {
|
||||
std::array<char, 16> version;
|
||||
};
|
||||
using RuleVersion = std::array<char, 0x10>;
|
||||
static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!");
|
||||
|
||||
struct ClockSnapshot {
|
||||
@ -152,8 +149,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) {
|
||||
return std::chrono::nanoseconds(a + b);
|
||||
}
|
||||
|
||||
constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTimePoint& a,
|
||||
SteadyClockTimePoint& b) {
|
||||
constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyClockTimePoint& a,
|
||||
const SteadyClockTimePoint& b) {
|
||||
R_UNLESS(out_seconds, ResultInvalidArgument);
|
||||
R_UNLESS(a.IdMatches(b), ResultInvalidArgument);
|
||||
R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(),
|
||||
@ -166,3 +163,111 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTi
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::TimeType> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(Service::PSC::Time::TimeType type, FormatContext& ctx) {
|
||||
const string_view name = [type] {
|
||||
using Service::PSC::Time::TimeType;
|
||||
switch (type) {
|
||||
case TimeType::UserSystemClock:
|
||||
return "UserSystemClock";
|
||||
case TimeType::NetworkSystemClock:
|
||||
return "NetworkSystemClock";
|
||||
case TimeType::LocalSystemClock:
|
||||
return "LocalSystemClock";
|
||||
}
|
||||
return "Invalid";
|
||||
}();
|
||||
return formatter<string_view>::format(name, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "[time_point={}]", time_point.time_point);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "[offset={} steady_time_point={}]", context.offset,
|
||||
context.steady_time_point.time_point);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "[{:02}/{:02}/{:04} {:02}:{:02}:{:02}]", calendar.day,
|
||||
calendar.month, calendar.year, calendar.hour, calendar.minute,
|
||||
calendar.second);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo>
|
||||
: fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "[weekday={} yearday={} name={} is_dst={} ut_offset={}]",
|
||||
additional.day_of_week, additional.day_of_year,
|
||||
additional.name.data(), additional.is_dst, additional.ut_offset);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const {
|
||||
return formatter<string_view>::format(name.data(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const {
|
||||
return formatter<string_view>::format(version.data(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const {
|
||||
return fmt::format_to(
|
||||
ctx.out(),
|
||||
"[user_context={} network_context={} user_time={} network_time={} "
|
||||
"user_calendar_time={} "
|
||||
"network_calendar_time={} user_calendar_additional_time={} "
|
||||
"network_calendar_additional_time={} steady_clock_time_point={} location={} "
|
||||
"is_automatic_correction_enabled={} type={}]",
|
||||
snapshot.user_context, snapshot.network_context, snapshot.user_time,
|
||||
snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time,
|
||||
snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time,
|
||||
snapshot.steady_clock_time_point, snapshot.location_name,
|
||||
snapshot.is_automatic_correction_enabled, snapshot.type);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint>
|
||||
: fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(),
|
||||
"[rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}]",
|
||||
time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount,
|
||||
time_point.lower, time_point.upper);
|
||||
}
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/power_state_service.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@ -11,39 +12,34 @@ IPowerStateRequestHandler::IPowerStateRequestHandler(
|
||||
power_state_request_manager} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle, "GetPowerStateRequestEventReadableHandle"},
|
||||
{1, &IPowerStateRequestHandler::GetAndClearPowerStateRequest, "GetAndClearPowerStateRequest"},
|
||||
{0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"},
|
||||
{1, D<&IPowerStateRequestHandler::GetAndClearPowerStateRequest>, "GetAndClearPowerStateRequest"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx) {
|
||||
Result IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(m_power_state_request_manager.GetReadableEvent());
|
||||
*out_event = &m_power_state_request_manager.GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IPowerStateRequestHandler::GetAndClearPowerStateRequest(HLERequestContext& ctx) {
|
||||
Result IPowerStateRequestHandler::GetAndClearPowerStateRequest(Out<bool> out_cleared,
|
||||
Out<u32> out_priority) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
u32 priority{};
|
||||
auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority);
|
||||
*out_cleared = cleared;
|
||||
|
||||
if (cleared) {
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(priority);
|
||||
rb.Push(cleared);
|
||||
return;
|
||||
*out_priority = priority;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(cleared);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/power_state_request_manager.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
@ -21,10 +22,10 @@ public:
|
||||
|
||||
~IPowerStateRequestHandler() override = default;
|
||||
|
||||
private:
|
||||
void GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx);
|
||||
void GetAndClearPowerStateRequest(HLERequestContext& ctx);
|
||||
Result GetPowerStateRequestEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetAndClearPowerStateRequest(Out<bool> out_cleared, Out<u32> out_priority);
|
||||
|
||||
private:
|
||||
Core::System& m_system;
|
||||
PowerStateRequestManager& m_power_state_request_manager;
|
||||
};
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/power_state_service.h"
|
||||
#include "core/hle/service/psc/time/service_manager.h"
|
||||
#include "core/hle/service/psc/time/static.h"
|
||||
@ -25,24 +26,24 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
|
||||
m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ServiceManager::Handle_GetStaticServiceAsUser, "GetStaticServiceAsUser"},
|
||||
{5, &ServiceManager::Handle_GetStaticServiceAsAdmin, "GetStaticServiceAsAdmin"},
|
||||
{6, &ServiceManager::Handle_GetStaticServiceAsRepair, "GetStaticServiceAsRepair"},
|
||||
{9, &ServiceManager::Handle_GetStaticServiceAsServiceManager, "GetStaticServiceAsServiceManager"},
|
||||
{10, &ServiceManager::Handle_SetupStandardSteadyClockCore, "SetupStandardSteadyClockCore"},
|
||||
{11, &ServiceManager::Handle_SetupStandardLocalSystemClockCore, "SetupStandardLocalSystemClockCore"},
|
||||
{12, &ServiceManager::Handle_SetupStandardNetworkSystemClockCore, "SetupStandardNetworkSystemClockCore"},
|
||||
{13, &ServiceManager::Handle_SetupStandardUserSystemClockCore, "SetupStandardUserSystemClockCore"},
|
||||
{14, &ServiceManager::Handle_SetupTimeZoneServiceCore, "SetupTimeZoneServiceCore"},
|
||||
{15, &ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore, "SetupEphemeralNetworkSystemClockCore"},
|
||||
{50, &ServiceManager::Handle_GetStandardLocalClockOperationEvent, "GetStandardLocalClockOperationEvent"},
|
||||
{51, &ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager, "GetStandardNetworkClockOperationEventForServiceManager"},
|
||||
{52, &ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager, "GetEphemeralNetworkClockOperationEventForServiceManager"},
|
||||
{60, &ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
|
||||
{100, &ServiceManager::Handle_SetStandardSteadyClockBaseTime, "SetStandardSteadyClockBaseTime"},
|
||||
{200, &ServiceManager::Handle_GetClosestAlarmUpdatedEvent, "GetClosestAlarmUpdatedEvent"},
|
||||
{201, &ServiceManager::Handle_CheckAndSignalAlarms, "CheckAndSignalAlarms"},
|
||||
{202, &ServiceManager::Handle_GetClosestAlarmInfo, "GetClosestAlarmInfo "},
|
||||
{0, D<&ServiceManager::GetStaticServiceAsUser>, "GetStaticServiceAsUser"},
|
||||
{5, D<&ServiceManager::GetStaticServiceAsAdmin>, "GetStaticServiceAsAdmin"},
|
||||
{6, D<&ServiceManager::GetStaticServiceAsRepair>, "GetStaticServiceAsRepair"},
|
||||
{9, D<&ServiceManager::GetStaticServiceAsServiceManager>, "GetStaticServiceAsServiceManager"},
|
||||
{10, D<&ServiceManager::SetupStandardSteadyClockCore>, "SetupStandardSteadyClockCore"},
|
||||
{11, D<&ServiceManager::SetupStandardLocalSystemClockCore>, "SetupStandardLocalSystemClockCore"},
|
||||
{12, D<&ServiceManager::SetupStandardNetworkSystemClockCore>, "SetupStandardNetworkSystemClockCore"},
|
||||
{13, D<&ServiceManager::SetupStandardUserSystemClockCore>, "SetupStandardUserSystemClockCore"},
|
||||
{14, D<&ServiceManager::SetupTimeZoneServiceCore>, "SetupTimeZoneServiceCore"},
|
||||
{15, D<&ServiceManager::SetupEphemeralNetworkSystemClockCore>, "SetupEphemeralNetworkSystemClockCore"},
|
||||
{50, D<&ServiceManager::GetStandardLocalClockOperationEvent>, "GetStandardLocalClockOperationEvent"},
|
||||
{51, D<&ServiceManager::GetStandardNetworkClockOperationEventForServiceManager>, "GetStandardNetworkClockOperationEventForServiceManager"},
|
||||
{52, D<&ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager>, "GetEphemeralNetworkClockOperationEventForServiceManager"},
|
||||
{60, D<&ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
|
||||
{100, D<&ServiceManager::SetStandardSteadyClockBaseTime>, "SetStandardSteadyClockBaseTime"},
|
||||
{200, D<&ServiceManager::GetClosestAlarmUpdatedEvent>, "GetClosestAlarmUpdatedEvent"},
|
||||
{201, D<&ServiceManager::CheckAndSignalAlarms>, "CheckAndSignalAlarms"},
|
||||
{202, D<&ServiceManager::GetClosestAlarmInfo>, "GetClosestAlarmInfo "},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
@ -52,302 +53,39 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
|
||||
m_ephemeral_system_context_writer.Link(m_ephemeral_operation);
|
||||
}
|
||||
|
||||
void ServiceManager::SetupSAndP() {
|
||||
if (!m_is_s_and_p_setup) {
|
||||
m_is_s_and_p_setup = true;
|
||||
m_server_manager.RegisterNamedService(
|
||||
"time:s", std::make_shared<StaticService>(
|
||||
m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
|
||||
m_server_manager.RegisterNamedService("time:p",
|
||||
std::make_shared<IPowerStateRequestHandler>(
|
||||
m_system, m_time->m_power_state_request_manager));
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceManager::CheckAndSetupServicesSAndP() {
|
||||
if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
|
||||
m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
|
||||
m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
|
||||
SetupSAndP();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsUser(HLERequestContext& ctx) {
|
||||
Result ServiceManager::GetStaticServiceAsUser(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsUser(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsAdmin(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsRepair(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsRepair(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsServiceManager(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
struct Parameters {
|
||||
bool reset_detected;
|
||||
Common::UUID clock_source_id;
|
||||
s64 rtc_offset;
|
||||
s64 internal_offset;
|
||||
s64 test_offset;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x30);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto params{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto res = SetupStandardSteadyClockCore(params.clock_source_id, params.rtc_offset,
|
||||
params.internal_offset, params.test_offset,
|
||||
params.reset_detected);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetupStandardLocalSystemClockCore(context, time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
auto accuracy{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetupStandardNetworkSystemClockCore(context, accuracy);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
struct Parameters {
|
||||
bool automatic_correction;
|
||||
SteadyClockTimePoint time_point;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x20);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto params{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto res = SetupStandardUserSystemClockCore(params.time_point, params.automatic_correction);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
struct Parameters {
|
||||
u32 location_count;
|
||||
LocationName name;
|
||||
SteadyClockTimePoint time_point;
|
||||
RuleVersion rule_version;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x50);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto params{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto rule_buffer{ctx.ReadBuffer()};
|
||||
|
||||
auto res = SetupTimeZoneServiceCore(params.name, params.time_point, params.rule_version,
|
||||
params.location_count, rule_buffer);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
auto res = SetupEphemeralNetworkSystemClockCore();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetStandardLocalClockOperationEvent(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetStandardNetworkClockOperationEventForServiceManager(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetEphemeralNetworkClockOperationEventForServiceManager(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto base_time{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetStandardSteadyClockBaseTime(base_time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetClosestAlarmUpdatedEvent(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_CheckAndSignalAlarms(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
auto res = CheckAndSignalAlarms();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetClosestAlarmInfo(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
AlarmInfo alarm_info{};
|
||||
bool is_valid{};
|
||||
s64 time{};
|
||||
auto res = GetClosestAlarmInfo(is_valid, alarm_info, time);
|
||||
|
||||
struct OutParameters {
|
||||
bool is_valid;
|
||||
AlarmInfo alarm_info;
|
||||
s64 time;
|
||||
};
|
||||
static_assert(sizeof(OutParameters) == 0x20);
|
||||
|
||||
OutParameters out_params{
|
||||
.is_valid = is_valid,
|
||||
.alarm_info = alarm_info,
|
||||
.time = time,
|
||||
};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(OutParameters) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<OutParameters>(out_params);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result ServiceManager::GetStaticService(std::shared_ptr<StaticService>& out_service,
|
||||
StaticServiceSetupInfo setup_info, const char* name) {
|
||||
out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service) {
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u"));
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service) {
|
||||
Result ServiceManager::GetStaticServiceAsAdmin(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a"));
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service) {
|
||||
Result ServiceManager::GetStaticServiceAsRepair(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r"));
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsServiceManager(
|
||||
std::shared_ptr<StaticService>& out_service) {
|
||||
Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm"));
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
|
||||
s64 internal_offset, s64 test_offset,
|
||||
bool is_rtc_reset_detected) {
|
||||
Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected,
|
||||
Common::UUID& clock_source_id, s64 rtc_offset,
|
||||
s64 internal_offset, s64 test_offset) {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. is_rtc_reset_detected={} clock_source_id={} rtc_offset={} "
|
||||
"internal_offset={} test_offset={}",
|
||||
is_rtc_reset_detected, clock_source_id.RawString(), rtc_offset, internal_offset,
|
||||
test_offset);
|
||||
|
||||
m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset,
|
||||
is_rtc_reset_detected);
|
||||
auto time = m_steady_clock.GetRawTime();
|
||||
@ -365,6 +103,10 @@ Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_i
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. context={} context.steady_time_point.clock_source_id={} time={}", context,
|
||||
context.steady_time_point.clock_source_id.RawString(), time);
|
||||
|
||||
m_local_system_clock.SetContextWriter(m_local_system_context_writer);
|
||||
m_local_system_clock.Initialize(context, time);
|
||||
|
||||
@ -374,12 +116,12 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con
|
||||
|
||||
Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context,
|
||||
s64 accuracy) {
|
||||
LOG_DEBUG(Service_Time, "called. context={} steady_time_point.clock_source_id={} accuracy={}",
|
||||
context, context.steady_time_point.clock_source_id.RawString(), accuracy);
|
||||
|
||||
// TODO this is a hack! The network clock should be updated independently, from the ntc service
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
||||
// to avoid it being stuck at 0.
|
||||
if (context == Service::PSC::Time::SystemClockContext{}) {
|
||||
m_local_system_clock.GetContext(context);
|
||||
}
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock.
|
||||
m_local_system_clock.GetContext(context);
|
||||
|
||||
m_network_system_clock.SetContextWriter(m_network_system_context_writer);
|
||||
m_network_system_clock.Initialize(context, accuracy);
|
||||
@ -388,14 +130,10 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
|
||||
bool automatic_correction) {
|
||||
// TODO this is a hack! The user clock should be updated independently, from the ntc service
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
||||
// to avoid it being stuck at 0.
|
||||
if (time_point == Service::PSC::Time::SteadyClockTimePoint{}) {
|
||||
m_local_system_clock.GetCurrentTimePoint(time_point);
|
||||
}
|
||||
Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction,
|
||||
SteadyClockTimePoint& time_point) {
|
||||
LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}",
|
||||
automatic_correction, time_point, time_point.clock_source_id.RawString());
|
||||
|
||||
m_user_system_clock.SetAutomaticCorrection(automatic_correction);
|
||||
m_user_system_clock.SetTimePointAndSignal(time_point);
|
||||
@ -406,10 +144,16 @@ Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& ti
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
|
||||
Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
|
||||
u32 location_count,
|
||||
SteadyClockTimePoint& time_point,
|
||||
RuleVersion& rule_version, u32 location_count,
|
||||
std::span<const u8> rule_buffer) {
|
||||
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. name={} rule_version={} location_count={} time_point={} "
|
||||
"clock_source_id={}",
|
||||
name, rule_version, location_count, time_point,
|
||||
time_point.clock_source_id.RawString());
|
||||
|
||||
if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) {
|
||||
LOG_ERROR(Service_Time, "Failed to parse time zone binary!");
|
||||
}
|
||||
@ -424,6 +168,8 @@ Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer);
|
||||
m_ephemeral_network_clock.SetInitialized();
|
||||
|
||||
@ -431,30 +177,41 @@ Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event) {
|
||||
*out_event = m_local_operation.m_event;
|
||||
Result ServiceManager::GetStandardLocalClockOperationEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_local_operation.m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager(
|
||||
Kernel::KEvent** out_event) {
|
||||
*out_event = m_network_operation.m_event;
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_network_operation.m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager(
|
||||
Kernel::KEvent** out_event) {
|
||||
*out_event = m_ephemeral_operation.m_event;
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_ephemeral_operation.m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
|
||||
Kernel::KEvent** out_event) {
|
||||
*out_event = &m_user_system_clock.GetEvent();
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_user_system_clock.GetEvent().GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
|
||||
LOG_DEBUG(Service_Time, "called. base_time={}", base_time);
|
||||
|
||||
m_steady_clock.SetRtcOffset(base_time);
|
||||
auto time = m_steady_clock.GetRawTime();
|
||||
auto ticks = m_system.CoreTiming().GetClockTicks();
|
||||
@ -468,26 +225,63 @@ Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event) {
|
||||
*out_event = &m_alarms.GetEvent();
|
||||
Result ServiceManager::GetClosestAlarmUpdatedEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_alarms.GetEvent().GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::CheckAndSignalAlarms() {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
m_alarms.CheckAndSignal();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time) {
|
||||
Result ServiceManager::GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info,
|
||||
Out<s64> out_time) {
|
||||
Alarm* alarm{nullptr};
|
||||
out_is_valid = m_alarms.GetClosestAlarm(&alarm);
|
||||
if (out_is_valid) {
|
||||
out_info = {
|
||||
*out_is_valid = m_alarms.GetClosestAlarm(&alarm);
|
||||
if (*out_is_valid) {
|
||||
*out_info = {
|
||||
.alert_time = alarm->GetAlertTime(),
|
||||
.priority = alarm->GetPriority(),
|
||||
};
|
||||
out_time = m_alarms.GetRawTime();
|
||||
*out_time = m_alarms.GetRawTime();
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. out_is_valid={} out_info.alert_time={} out_info.priority={}, out_time={}",
|
||||
*out_is_valid, out_info->alert_time, out_info->priority, *out_time);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void ServiceManager::CheckAndSetupServicesSAndP() {
|
||||
if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
|
||||
m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
|
||||
m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
|
||||
SetupSAndP();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceManager::SetupSAndP() {
|
||||
if (!m_is_s_and_p_setup) {
|
||||
m_is_s_and_p_setup = true;
|
||||
m_server_manager.RegisterNamedService(
|
||||
"time:s", std::make_shared<StaticService>(
|
||||
m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
|
||||
m_server_manager.RegisterNamedService("time:p",
|
||||
std::make_shared<IPowerStateRequestHandler>(
|
||||
m_system, m_time->m_power_state_request_manager));
|
||||
}
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticService(OutInterface<StaticService> out_service,
|
||||
StaticServiceSetupInfo setup_info, const char* name) {
|
||||
*out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@ -29,55 +30,38 @@ public:
|
||||
ServerManager* server_manager);
|
||||
~ServiceManager() override = default;
|
||||
|
||||
Result GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service);
|
||||
Result GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service);
|
||||
Result GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service);
|
||||
Result GetStaticServiceAsServiceManager(std::shared_ptr<StaticService>& out_service);
|
||||
Result SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
|
||||
s64 internal_offset, s64 test_offset,
|
||||
bool is_rtc_reset_detected);
|
||||
Result GetStaticServiceAsUser(OutInterface<StaticService> out_service);
|
||||
Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service);
|
||||
Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service);
|
||||
Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service);
|
||||
Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id,
|
||||
s64 rtc_offset, s64 internal_offset, s64 test_offset);
|
||||
Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time);
|
||||
Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy);
|
||||
Result SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
|
||||
bool automatic_correction);
|
||||
Result SetupTimeZoneServiceCore(LocationName& name, SteadyClockTimePoint& time_point,
|
||||
RuleVersion& rule_version, u32 location_count,
|
||||
std::span<const u8> rule_buffer);
|
||||
Result SetupStandardUserSystemClockCore(bool automatic_correction,
|
||||
SteadyClockTimePoint& time_point);
|
||||
Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
|
||||
u32 location_count, SteadyClockTimePoint& time_point,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer);
|
||||
Result SetupEphemeralNetworkSystemClockCore();
|
||||
Result GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event);
|
||||
Result GetStandardNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
|
||||
Result GetEphemeralNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
|
||||
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(Kernel::KEvent** out_event);
|
||||
Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetStandardNetworkClockOperationEventForServiceManager(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetEphemeralNetworkClockOperationEventForServiceManager(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result SetStandardSteadyClockBaseTime(s64 base_time);
|
||||
Result GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event);
|
||||
Result GetClosestAlarmUpdatedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result CheckAndSignalAlarms();
|
||||
Result GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time);
|
||||
Result GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Out<s64> out_time);
|
||||
|
||||
private:
|
||||
void CheckAndSetupServicesSAndP();
|
||||
void SetupSAndP();
|
||||
Result GetStaticService(std::shared_ptr<StaticService>& out_service,
|
||||
Result GetStaticService(OutInterface<StaticService> out_service,
|
||||
StaticServiceSetupInfo setup_info, const char* name);
|
||||
|
||||
void Handle_GetStaticServiceAsUser(HLERequestContext& ctx);
|
||||
void Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx);
|
||||
void Handle_GetStaticServiceAsRepair(HLERequestContext& ctx);
|
||||
void Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx);
|
||||
void Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx);
|
||||
void Handle_GetStandardNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
|
||||
void Handle_GetEphemeralNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(HLERequestContext& ctx);
|
||||
void Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx);
|
||||
void Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx);
|
||||
void Handle_CheckAndSignalAlarms(HLERequestContext& ctx);
|
||||
void Handle_GetClosestAlarmInfo(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
std::shared_ptr<TimeManager> m_time;
|
||||
ServerManager& m_server_manager;
|
||||
|
@ -1,9 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h"
|
||||
#include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h"
|
||||
#include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h"
|
||||
@ -39,358 +41,122 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup
|
||||
m_time->m_shared_memory} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||
{1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
||||
{2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"},
|
||||
{20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
|
||||
{50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"},
|
||||
{51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"},
|
||||
{100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||
{300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"},
|
||||
{401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"},
|
||||
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
|
||||
{1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"},
|
||||
{2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"},
|
||||
{3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"},
|
||||
{4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"},
|
||||
{5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"},
|
||||
{20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
|
||||
{50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"},
|
||||
{51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"},
|
||||
{100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||
{300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"},
|
||||
{401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshotImpl(ClockSnapshot& out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context, TimeType type) {
|
||||
out_snapshot.user_context = user_context;
|
||||
out_snapshot.network_context = network_context;
|
||||
Result StaticService::GetStandardUserSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_TRY(
|
||||
m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot.steady_clock_time_point));
|
||||
|
||||
out_snapshot.is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
|
||||
R_TRY(m_time_zone.GetLocationName(out_snapshot.location_name));
|
||||
|
||||
R_TRY(GetTimeFromTimePointAndContext(
|
||||
&out_snapshot.user_time, out_snapshot.steady_clock_time_point, out_snapshot.user_context));
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.user_calendar_time,
|
||||
out_snapshot.user_calendar_additional_time,
|
||||
out_snapshot.user_time));
|
||||
|
||||
if (GetTimeFromTimePointAndContext(&out_snapshot.network_time,
|
||||
out_snapshot.steady_clock_time_point,
|
||||
out_snapshot.network_context) != ResultSuccess) {
|
||||
out_snapshot.network_time = 0;
|
||||
}
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.network_calendar_time,
|
||||
out_snapshot.network_calendar_additional_time,
|
||||
out_snapshot.network_time));
|
||||
out_snapshot.type = type;
|
||||
out_snapshot.unk_CE = 0;
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
|
||||
m_setup_info.can_write_user_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
|
||||
Result StaticService::GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetStandardUserSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetStandardNetworkSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SteadyClock> service{};
|
||||
auto res = GetStandardSteadyClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<TimeZoneService> service{};
|
||||
auto res = GetTimeZoneService(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetStandardLocalSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetEphemeralNetworkSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KSharedMemory* shared_memory{};
|
||||
auto res = GetSharedMemoryNativeHandle(&shared_memory);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(shared_memory);
|
||||
}
|
||||
|
||||
void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(m_setup_info.can_write_steady_clock ? ResultNotImplemented : ResultPermissionDenied);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool is_enabled{};
|
||||
auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push<bool>(is_enabled);
|
||||
}
|
||||
|
||||
void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto automatic_correction{rp.Pop<bool>()};
|
||||
|
||||
auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool is_sufficient{};
|
||||
auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push<bool>(is_sufficient);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
SteadyClockTimePoint time_point{};
|
||||
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<SteadyClockTimePoint>(time_point);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
|
||||
s64 time{};
|
||||
auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push<s64>(time);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto type{rp.PopEnum<TimeType>()};
|
||||
|
||||
ClockSnapshot snapshot{};
|
||||
auto res = GetClockSnapshot(snapshot, type);
|
||||
|
||||
ctx.WriteBuffer(snapshot);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto clock_type{rp.PopEnum<TimeType>()};
|
||||
[[maybe_unused]] auto alignment{rp.Pop<u32>()};
|
||||
auto user_context{rp.PopRaw<SystemClockContext>()};
|
||||
auto network_context{rp.PopRaw<SystemClockContext>()};
|
||||
|
||||
ClockSnapshot snapshot{};
|
||||
auto res =
|
||||
GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type);
|
||||
|
||||
ctx.WriteBuffer(snapshot);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
ClockSnapshot a{};
|
||||
ClockSnapshot b{};
|
||||
|
||||
auto a_buffer{ctx.ReadBuffer(0)};
|
||||
auto b_buffer{ctx.ReadBuffer(1)};
|
||||
|
||||
std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
|
||||
std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
|
||||
|
||||
s64 difference{};
|
||||
auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(difference);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
ClockSnapshot a{};
|
||||
ClockSnapshot b{};
|
||||
|
||||
auto a_buffer{ctx.ReadBuffer(0)};
|
||||
auto b_buffer{ctx.ReadBuffer(1)};
|
||||
|
||||
std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
|
||||
std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
|
||||
|
||||
s64 time{};
|
||||
auto res = CalculateSpanBetween(time, a, b);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(time);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result StaticService::GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
|
||||
m_setup_info.can_write_user_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
Result StaticService::GetStandardSteadyClock(OutInterface<SteadyClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Result StaticService::GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service) {
|
||||
out_service =
|
||||
*out_service =
|
||||
std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) {
|
||||
out_service =
|
||||
Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_service =
|
||||
std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone,
|
||||
m_setup_info.can_write_timezone_device_location);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock,
|
||||
m_setup_info.can_write_local_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
Result StaticService::GetStandardLocalSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock,
|
||||
m_setup_info.can_write_local_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
Result StaticService::GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
|
||||
Result StaticService::GetSharedMemoryNativeHandle(
|
||||
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_shared_memory = &m_shared_memory.GetKSharedMemory();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled) {
|
||||
Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_UNLESS(m_setup_info.can_write_steady_clock, ResultPermissionDenied);
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
Out<bool> out_is_enabled) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); });
|
||||
|
||||
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
|
||||
|
||||
out_is_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
*out_is_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
bool automatic_correction) {
|
||||
LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
|
||||
|
||||
R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied);
|
||||
@ -407,22 +173,35 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) {
|
||||
out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
|
||||
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
|
||||
|
||||
*out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
SteadyClockTimePoint& out_time_point) {
|
||||
Out<SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
|
||||
|
||||
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
|
||||
|
||||
m_user_system_clock.GetTimePoint(out_time_point);
|
||||
m_user_system_clock.GetTimePoint(*out_time_point);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
|
||||
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
|
||||
SystemClockContext& context) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
|
||||
|
||||
R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized);
|
||||
|
||||
SteadyClockTimePoint time_point{};
|
||||
@ -433,12 +212,16 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
|
||||
auto one_second_ns{
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()};
|
||||
auto ticks{m_system.CoreTiming().GetClockTicks()};
|
||||
auto current_time{ConvertToTimeSpan(ticks).count()};
|
||||
out_time = ((context.offset + time_point.time_point) - (current_time / one_second_ns));
|
||||
auto current_time_ns{ConvertToTimeSpan(ticks).count()};
|
||||
*out_time = ((context.offset + time_point.time_point) - (current_time_ns / one_second_ns));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type) {
|
||||
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) {
|
||||
SCOPE_EXIT(
|
||||
{ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
|
||||
|
||||
SystemClockContext user_context{};
|
||||
R_TRY(m_user_system_clock.GetContext(user_context));
|
||||
|
||||
@ -448,53 +231,101 @@ Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType typ
|
||||
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
|
||||
Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type,
|
||||
OutClockSnapshot out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context,
|
||||
TimeType type) {
|
||||
SystemClockContext& network_context) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. type={} user_context={} network_context={} out_snapshot={}", type,
|
||||
user_context, network_context, *out_snapshot);
|
||||
});
|
||||
|
||||
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
|
||||
}
|
||||
|
||||
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(s64& out_time,
|
||||
ClockSnapshot& a,
|
||||
ClockSnapshot& b) {
|
||||
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
|
||||
InClockSnapshot a,
|
||||
InClockSnapshot b) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference);
|
||||
});
|
||||
|
||||
auto diff_s =
|
||||
std::chrono::seconds(b.user_context.offset) - std::chrono::seconds(a.user_context.offset);
|
||||
std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset);
|
||||
|
||||
if (a.user_context == b.user_context ||
|
||||
!a.user_context.steady_time_point.IdMatches(b.user_context.steady_time_point)) {
|
||||
out_time = 0;
|
||||
if (a->user_context == b->user_context ||
|
||||
!a->user_context.steady_time_point.IdMatches(b->user_context.steady_time_point)) {
|
||||
*out_difference = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
if (!a.is_automatic_correction_enabled || !b.is_automatic_correction_enabled) {
|
||||
out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
if (!a->is_automatic_correction_enabled || !b->is_automatic_correction_enabled) {
|
||||
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
if (a.network_context.steady_time_point.IdMatches(a.steady_clock_time_point) ||
|
||||
b.network_context.steady_time_point.IdMatches(b.steady_clock_time_point)) {
|
||||
out_time = 0;
|
||||
if (a->network_context.steady_time_point.IdMatches(a->steady_clock_time_point) ||
|
||||
b->network_context.steady_time_point.IdMatches(b->steady_clock_time_point)) {
|
||||
*out_difference = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b) {
|
||||
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
|
||||
InClockSnapshot b) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
|
||||
|
||||
s64 time_s{};
|
||||
auto res =
|
||||
GetSpanBetweenTimePoints(&time_s, a.steady_clock_time_point, b.steady_clock_time_point);
|
||||
GetSpanBetweenTimePoints(&time_s, a->steady_clock_time_point, b->steady_clock_time_point);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
R_UNLESS(a.network_time != 0 && b.network_time != 0, ResultTimeNotFound);
|
||||
time_s = b.network_time - a.network_time;
|
||||
R_UNLESS(a->network_time != 0 && b->network_time != 0, ResultTimeNotFound);
|
||||
time_s = b->network_time - a->network_time;
|
||||
}
|
||||
|
||||
out_time =
|
||||
*out_time =
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshotImpl(OutClockSnapshot out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context, TimeType type) {
|
||||
out_snapshot->user_context = user_context;
|
||||
out_snapshot->network_context = network_context;
|
||||
|
||||
R_TRY(
|
||||
m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot->steady_clock_time_point));
|
||||
|
||||
out_snapshot->is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
|
||||
R_TRY(m_time_zone.GetLocationName(out_snapshot->location_name));
|
||||
|
||||
R_TRY(GetTimeFromTimePointAndContext(&out_snapshot->user_time,
|
||||
out_snapshot->steady_clock_time_point,
|
||||
out_snapshot->user_context));
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->user_calendar_time,
|
||||
out_snapshot->user_calendar_additional_time,
|
||||
out_snapshot->user_time));
|
||||
|
||||
if (GetTimeFromTimePointAndContext(&out_snapshot->network_time,
|
||||
out_snapshot->steady_clock_time_point,
|
||||
out_snapshot->network_context) != ResultSuccess) {
|
||||
out_snapshot->network_time = 0;
|
||||
}
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->network_calendar_time,
|
||||
out_snapshot->network_calendar_additional_time,
|
||||
out_snapshot->network_time));
|
||||
out_snapshot->type = type;
|
||||
out_snapshot->unk_CE = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
@ -29,58 +30,44 @@ class EphemeralNetworkSystemClockCore;
|
||||
class SharedMemory;
|
||||
|
||||
class StaticService final : public ServiceFramework<StaticService> {
|
||||
using InClockSnapshot = InLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
|
||||
using OutClockSnapshot = OutLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
|
||||
|
||||
public:
|
||||
explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info,
|
||||
std::shared_ptr<TimeManager> time, const char* name);
|
||||
|
||||
~StaticService() override = default;
|
||||
|
||||
Result GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service);
|
||||
Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service);
|
||||
Result GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory);
|
||||
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled);
|
||||
Result GetStandardUserSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetStandardSteadyClock(OutInterface<SteadyClock> out_service);
|
||||
Result GetTimeZoneService(OutInterface<TimeZoneService> out_service);
|
||||
Result GetStandardLocalSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
|
||||
Result SetStandardSteadyClockInternalOffset(s64 offset_ns);
|
||||
Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
|
||||
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
|
||||
Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
|
||||
Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient);
|
||||
Result GetStandardUserSystemClockInitialYear(Out<s32> out_year);
|
||||
Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
|
||||
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
SteadyClockTimePoint& out_time_point);
|
||||
Result CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, SystemClockContext& context);
|
||||
Result GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type);
|
||||
Result GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
|
||||
Out<SteadyClockTimePoint> out_time_point);
|
||||
Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
|
||||
SystemClockContext& context);
|
||||
Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type);
|
||||
Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context,
|
||||
TimeType type);
|
||||
Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, ClockSnapshot& a,
|
||||
ClockSnapshot& b);
|
||||
Result CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b);
|
||||
SystemClockContext& network_context);
|
||||
Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
|
||||
InClockSnapshot a, InClockSnapshot b);
|
||||
Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b);
|
||||
|
||||
private:
|
||||
Result GetClockSnapshotImpl(ClockSnapshot& out_snapshot, SystemClockContext& user_context,
|
||||
Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context,
|
||||
SystemClockContext& network_context, TimeType type);
|
||||
|
||||
void Handle_GetStandardUserSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetStandardSteadyClock(HLERequestContext& ctx);
|
||||
void Handle_GetTimeZoneService(HLERequestContext& ctx);
|
||||
void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx);
|
||||
void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx);
|
||||
void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx);
|
||||
void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
|
||||
void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx);
|
||||
void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
|
||||
void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
|
||||
void Handle_GetClockSnapshot(HLERequestContext& ctx);
|
||||
void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
|
||||
void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
|
||||
void Handle_CalculateSpanBetween(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
StaticServiceSetupInfo m_setup_info;
|
||||
std::shared_ptr<TimeManager> m_time;
|
||||
|
@ -1,7 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/steady_clock.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@ -14,114 +16,40 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
|
||||
can_write_uninitialized_clock} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"},
|
||||
{2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"},
|
||||
{3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"},
|
||||
{100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"},
|
||||
{101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"},
|
||||
{102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"},
|
||||
{200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"},
|
||||
{0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"},
|
||||
{2, D<&SteadyClock::GetTestOffset>, "GetTestOffset"},
|
||||
{3, D<&SteadyClock::SetTestOffset>, "SetTestOffset"},
|
||||
{100, D<&SteadyClock::GetRtcValue>, "GetRtcValue"},
|
||||
{101, D<&SteadyClock::IsRtcResetDetected>, "IsRtcResetDetected"},
|
||||
{102, D<&SteadyClock::GetSetupResultValue>, "GetSetupResultValue"},
|
||||
{200, D<&SteadyClock::GetInternalOffset>, "GetInternalOffset"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetCurrentTimePoint(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
|
||||
|
||||
SteadyClockTimePoint time_point{};
|
||||
auto res = GetCurrentTimePoint(time_point);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<SteadyClockTimePoint>(time_point);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetTestOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s64 test_offset{};
|
||||
auto res = GetTestOffset(test_offset);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(test_offset);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_SetTestOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto test_offset{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetTestOffset(test_offset);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetRtcValue(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s64 rtc_value{};
|
||||
auto res = GetRtcValue(rtc_value);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(rtc_value);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_IsRtcResetDetected(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool reset_detected{false};
|
||||
auto res = IsRtcResetDetected(reset_detected);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(reset_detected);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetSetupResultValue(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Result result_value{ResultSuccess};
|
||||
auto res = GetSetupResultValue(result_value);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(result_value);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetInternalOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s64 internal_offset{};
|
||||
auto res = GetInternalOffset(internal_offset);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(internal_offset);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result SteadyClock::GetCurrentTimePoint(SteadyClockTimePoint& out_time_point) {
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetCurrentTimePoint(out_time_point));
|
||||
R_RETURN(m_clock_core.GetCurrentTimePoint(*out_time_point));
|
||||
}
|
||||
|
||||
Result SteadyClock::GetTestOffset(s64& out_test_offset) {
|
||||
Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_test_offset = m_clock_core.GetTestOffset();
|
||||
*out_test_offset = m_clock_core.GetTestOffset();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::SetTestOffset(s64 test_offset) {
|
||||
LOG_DEBUG(Service_Time, "called. test_offset={}", test_offset);
|
||||
|
||||
R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied);
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
@ -130,34 +58,43 @@ Result SteadyClock::SetTestOffset(s64 test_offset) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::GetRtcValue(s64& out_rtc_value) {
|
||||
Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetRtcValue(out_rtc_value));
|
||||
R_RETURN(m_clock_core.GetRtcValue(*out_rtc_value));
|
||||
}
|
||||
|
||||
Result SteadyClock::IsRtcResetDetected(bool& out_is_detected) {
|
||||
Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_is_detected = m_clock_core.IsResetDetected();
|
||||
*out_is_detected = m_clock_core.IsResetDetected();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::GetSetupResultValue(Result& out_result) {
|
||||
Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_result = m_clock_core.GetSetupResultValue();
|
||||
*out_result = m_clock_core.GetSetupResultValue();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::GetInternalOffset(s64& out_internal_offset) {
|
||||
Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) {
|
||||
SCOPE_EXIT(
|
||||
{ LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_internal_offset = m_clock_core.GetInternalOffset();
|
||||
*out_internal_offset = m_clock_core.GetInternalOffset();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@ -22,23 +23,15 @@ public:
|
||||
|
||||
~SteadyClock() override = default;
|
||||
|
||||
Result GetCurrentTimePoint(SteadyClockTimePoint& out_time_point);
|
||||
Result GetTestOffset(s64& out_test_offset);
|
||||
Result GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point);
|
||||
Result GetTestOffset(Out<s64> out_test_offset);
|
||||
Result SetTestOffset(s64 test_offset);
|
||||
Result GetRtcValue(s64& out_rtc_value);
|
||||
Result IsRtcResetDetected(bool& out_is_detected);
|
||||
Result GetSetupResultValue(Result& out_result);
|
||||
Result GetInternalOffset(s64& out_internal_offset);
|
||||
Result GetRtcValue(Out<s64> out_rtc_value);
|
||||
Result IsRtcResetDetected(Out<bool> out_is_detected);
|
||||
Result GetSetupResultValue(Out<Result> out_result);
|
||||
Result GetInternalOffset(Out<s64> out_internal_offset);
|
||||
|
||||
private:
|
||||
void Handle_GetCurrentTimePoint(HLERequestContext& ctx);
|
||||
void Handle_GetTestOffset(HLERequestContext& ctx);
|
||||
void Handle_SetTestOffset(HLERequestContext& ctx);
|
||||
void Handle_GetRtcValue(HLERequestContext& ctx);
|
||||
void Handle_IsRtcResetDetected(HLERequestContext& ctx);
|
||||
void Handle_GetSetupResultValue(HLERequestContext& ctx);
|
||||
void Handle_GetInternalOffset(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
StandardSteadyClockCore& m_clock_core;
|
||||
|
@ -1,7 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/system_clock.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@ -13,83 +15,28 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo
|
||||
can_write_uninitialized_clock} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &SystemClock::Handle_GetCurrentTime, "GetCurrentTime"},
|
||||
{1, &SystemClock::Handle_SetCurrentTime, "SetCurrentTime"},
|
||||
{2, &SystemClock::Handle_GetSystemClockContext, "GetSystemClockContext"},
|
||||
{3, &SystemClock::Handle_SetSystemClockContext, "SetSystemClockContext"},
|
||||
{4, &SystemClock::Handle_GetOperationEventReadableHandle, "GetOperationEventReadableHandle"},
|
||||
{0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"},
|
||||
{1, D<&SystemClock::SetCurrentTime>, "SetCurrentTime"},
|
||||
{2, D<&SystemClock::GetSystemClockContext>, "GetSystemClockContext"},
|
||||
{3, D<&SystemClock::SetSystemClockContext>, "SetSystemClockContext"},
|
||||
{4, D<&SystemClock::GetOperationEventReadableHandle>, "GetOperationEventReadableHandle"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_GetCurrentTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result SystemClock::GetCurrentTime(Out<s64> out_time) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); });
|
||||
|
||||
s64 time{};
|
||||
auto res = GetCurrentTime(time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push<s64>(time);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_SetCurrentTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetCurrentTime(time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_GetSystemClockContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
SystemClockContext context{};
|
||||
auto res = GetSystemClockContext(context);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SystemClockContext) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<SystemClockContext>(context);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_SetSystemClockContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
|
||||
auto res = SetSystemClockContext(context);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_GetOperationEventReadableHandle(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetOperationEventReadableHandle(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event->GetReadableEvent());
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result SystemClock::GetCurrentTime(s64& out_time) {
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetCurrentTime(&out_time));
|
||||
R_RETURN(m_clock_core.GetCurrentTime(out_time.Get()));
|
||||
}
|
||||
|
||||
Result SystemClock::SetCurrentTime(s64 time) {
|
||||
LOG_DEBUG(Service_Time, "called. time={}", time);
|
||||
|
||||
R_UNLESS(m_can_write_clock, ResultPermissionDenied);
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
@ -97,14 +44,18 @@ Result SystemClock::SetCurrentTime(s64 time) {
|
||||
R_RETURN(m_clock_core.SetCurrentTime(time));
|
||||
}
|
||||
|
||||
Result SystemClock::GetSystemClockContext(SystemClockContext& out_context) {
|
||||
Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetContext(out_context));
|
||||
R_RETURN(m_clock_core.GetContext(*out_context));
|
||||
}
|
||||
|
||||
Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
|
||||
LOG_DEBUG(Service_Time, "called. context={}", context);
|
||||
|
||||
R_UNLESS(m_can_write_clock, ResultPermissionDenied);
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
@ -112,7 +63,10 @@ Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
|
||||
R_RETURN(m_clock_core.SetContextAndWrite(context));
|
||||
}
|
||||
|
||||
Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) {
|
||||
Result SystemClock::GetOperationEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
if (!m_operation_event) {
|
||||
m_operation_event = std::make_unique<OperationEvent>(m_system);
|
||||
R_UNLESS(m_operation_event != nullptr, ResultFailed);
|
||||
@ -120,7 +74,7 @@ Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event)
|
||||
m_clock_core.LinkOperationEvent(*m_operation_event);
|
||||
}
|
||||
|
||||
*out_event = m_operation_event->m_event;
|
||||
*out_event = &m_operation_event->m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@ -22,19 +23,13 @@ public:
|
||||
|
||||
~SystemClock() override = default;
|
||||
|
||||
Result GetCurrentTime(s64& out_time);
|
||||
Result GetCurrentTime(Out<s64> out_time);
|
||||
Result SetCurrentTime(s64 time);
|
||||
Result GetSystemClockContext(SystemClockContext& out_context);
|
||||
Result GetSystemClockContext(Out<SystemClockContext> out_context);
|
||||
Result SetSystemClockContext(SystemClockContext& context);
|
||||
Result GetOperationEventReadableHandle(Kernel::KEvent** out_event);
|
||||
Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
|
||||
private:
|
||||
void Handle_GetCurrentTime(HLERequestContext& ctx);
|
||||
void Handle_SetCurrentTime(HLERequestContext& ctx);
|
||||
void Handle_GetSystemClockContext(HLERequestContext& ctx);
|
||||
void Handle_SetSystemClockContext(HLERequestContext& ctx);
|
||||
void Handle_GetOperationEventReadableHandle(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
SystemClockCore& m_clock_core;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
namespace {
|
||||
constexpr Result ValidateRule(Tz::Rule& rule) {
|
||||
constexpr Result ValidateRule(const Tz::Rule& rule) {
|
||||
if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) ||
|
||||
rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) ||
|
||||
rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) {
|
||||
@ -26,7 +26,7 @@ constexpr Result ValidateRule(Tz::Rule& rule) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
constexpr bool GetTimeZoneTime(s64& out_time, Tz::Rule& rule, s64 time, s32 index,
|
||||
constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s32 index,
|
||||
s32 index_offset) {
|
||||
s32 found_idx{};
|
||||
s32 expected_index{index + index_offset};
|
||||
@ -107,7 +107,7 @@ Result TimeZone::GetTimePoint(SteadyClockTimePoint& out_time_point) {
|
||||
|
||||
Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule) {
|
||||
const Tz::Rule& rule) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule));
|
||||
}
|
||||
@ -140,11 +140,11 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary)
|
||||
R_RETURN(ParseBinaryImpl(out_rule, binary));
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule) {
|
||||
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||
const CalendarTime& calendar, const Tz::Rule& rule) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1);
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, rule, -1);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res == ResultTimeZoneNotFound) {
|
||||
@ -157,11 +157,11 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 ou
|
||||
R_RETURN(res);
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
|
||||
u32 out_times_count, CalendarTime& calendar) {
|
||||
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
||||
size_t out_times_max_count, const CalendarTime& calendar) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, m_my_rule, -1);
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, m_my_rule, -1);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res == ResultTimeZoneNotFound) {
|
||||
@ -183,7 +183,7 @@ Result TimeZone::ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary)
|
||||
|
||||
Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule) {
|
||||
const Tz::Rule& rule) {
|
||||
R_TRY(ValidateRule(rule));
|
||||
|
||||
Tz::CalendarTimeInternal calendar_internal{};
|
||||
@ -212,20 +212,23 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule, s32 is_dst) {
|
||||
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times,
|
||||
size_t out_times_max_count, const CalendarTime& calendar,
|
||||
const Tz::Rule& rule, s32 is_dst) {
|
||||
R_TRY(ValidateRule(rule));
|
||||
|
||||
calendar.month -= 1;
|
||||
calendar.year -= 1900;
|
||||
CalendarTime local_calendar{calendar};
|
||||
|
||||
local_calendar.month -= 1;
|
||||
local_calendar.year -= 1900;
|
||||
|
||||
Tz::CalendarTimeInternal internal{
|
||||
.tm_sec = calendar.second,
|
||||
.tm_min = calendar.minute,
|
||||
.tm_hour = calendar.hour,
|
||||
.tm_mday = calendar.day,
|
||||
.tm_mon = calendar.month,
|
||||
.tm_year = calendar.year,
|
||||
.tm_sec = local_calendar.second,
|
||||
.tm_min = local_calendar.minute,
|
||||
.tm_hour = local_calendar.hour,
|
||||
.tm_mday = local_calendar.day,
|
||||
.tm_mon = local_calendar.month,
|
||||
.tm_year = local_calendar.year,
|
||||
.tm_wday = 0,
|
||||
.tm_yday = 0,
|
||||
.tm_isdst = is_dst,
|
||||
@ -243,9 +246,9 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u3
|
||||
R_RETURN(ResultTimeZoneNotFound);
|
||||
}
|
||||
|
||||
if (internal.tm_sec != calendar.second || internal.tm_min != calendar.minute ||
|
||||
internal.tm_hour != calendar.hour || internal.tm_mday != calendar.day ||
|
||||
internal.tm_mon != calendar.month || internal.tm_year != calendar.year) {
|
||||
if (internal.tm_sec != local_calendar.second || internal.tm_min != local_calendar.minute ||
|
||||
internal.tm_hour != local_calendar.hour || internal.tm_mday != local_calendar.day ||
|
||||
internal.tm_mon != local_calendar.month || internal.tm_year != local_calendar.year) {
|
||||
R_RETURN(ResultTimeZoneNotFound);
|
||||
}
|
||||
|
||||
@ -254,7 +257,7 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u3
|
||||
}
|
||||
|
||||
out_times[0] = time;
|
||||
if (out_times_count < 2) {
|
||||
if (out_times_max_count < 2) {
|
||||
out_count = 1;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
@ -32,23 +32,24 @@ public:
|
||||
Result GetTimePoint(SteadyClockTimePoint& out_time_point);
|
||||
|
||||
Result ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
const Tz::Rule& rule);
|
||||
Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time,
|
||||
CalendarAdditionalInfo& calendar_additional, s64 time);
|
||||
Result ParseBinary(LocationName& name, std::span<const u8> binary);
|
||||
Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||
const CalendarTime& calendar, const Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
||||
size_t out_times_max_count, const CalendarTime& calendar);
|
||||
|
||||
private:
|
||||
Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule);
|
||||
Result ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule, s32 is_dst);
|
||||
const Tz::Rule& rule);
|
||||
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||
const CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
|
||||
|
||||
bool m_initialized{};
|
||||
std::recursive_mutex m_mutex;
|
||||
|
@ -2,7 +2,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <tz/tz.h>
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/time_zone_service.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@ -14,240 +17,78 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore&
|
||||
can_write_timezone_device_location} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"},
|
||||
{1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"},
|
||||
{2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"},
|
||||
{3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"},
|
||||
{4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"},
|
||||
{5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
|
||||
{6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"},
|
||||
{8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"},
|
||||
{20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"},
|
||||
{100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"},
|
||||
{101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
||||
{201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"},
|
||||
{202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
|
||||
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
||||
{1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"},
|
||||
{2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"},
|
||||
{3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"},
|
||||
{4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"},
|
||||
{5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"},
|
||||
{6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"},
|
||||
{8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"},
|
||||
{20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"},
|
||||
{100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"},
|
||||
{101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"},
|
||||
{201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"},
|
||||
{202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
|
||||
|
||||
LocationName name{};
|
||||
auto res = GetDeviceLocationName(name);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(LocationName) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<LocationName>(name);
|
||||
R_RETURN(m_time_zone.GetLocationName(*out_location_name));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
[[maybe_unused]] auto name{rp.PopRaw<LocationName>()};
|
||||
|
||||
if (!m_can_write_timezone_device_location) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultPermissionDenied);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
|
||||
|
||||
u32 count{};
|
||||
auto res = GetTotalLocationNameCount(count);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
R_RETURN(m_time_zone.GetTotalLocationCount(*out_count));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::LoadLocationNameList(
|
||||
Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
|
||||
|
||||
RuleVersion rule_version{};
|
||||
auto res = GetTimeZoneRuleVersion(rule_version);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(RuleVersion) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<RuleVersion>(rule_version);
|
||||
R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
|
||||
Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}",
|
||||
*out_location_name, *out_time_point);
|
||||
});
|
||||
|
||||
LocationName name{};
|
||||
SteadyClockTimePoint time_point{};
|
||||
auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(LocationName) / sizeof(u32)) +
|
||||
(sizeof(SteadyClockTimePoint) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<LocationName>(name);
|
||||
rb.PushRaw<SteadyClockTimePoint>(time_point);
|
||||
R_TRY(m_time_zone.GetLocationName(*out_location_name));
|
||||
R_RETURN(m_time_zone.GetTimePoint(*out_time_point));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
|
||||
LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) {
|
||||
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto name{rp.PopRaw<LocationName>()};
|
||||
|
||||
auto binary{ctx.ReadBuffer()};
|
||||
auto res = SetDeviceLocationNameWithTimeZoneRule(name, binary);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
auto binary{ctx.ReadBuffer()};
|
||||
|
||||
Tz::Rule rule{};
|
||||
auto res = ParseTimeZoneBinary(rule, binary);
|
||||
|
||||
ctx.WriteBuffer(rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
auto rule_buffer{ctx.ReadBuffer()};
|
||||
Tz::Rule rule{};
|
||||
std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule));
|
||||
|
||||
CalendarTime calendar_time{};
|
||||
CalendarAdditionalInfo additional_info{};
|
||||
auto res = ToCalendarTime(calendar_time, additional_info, time, rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) +
|
||||
(sizeof(CalendarAdditionalInfo) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<CalendarTime>(calendar_time);
|
||||
rb.PushRaw<CalendarAdditionalInfo>(additional_info);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
CalendarTime calendar_time{};
|
||||
CalendarAdditionalInfo additional_info{};
|
||||
auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) +
|
||||
(sizeof(CalendarAdditionalInfo) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<CalendarTime>(calendar_time);
|
||||
rb.PushRaw<CalendarAdditionalInfo>(additional_info);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar{rp.PopRaw<CalendarTime>()};
|
||||
|
||||
auto binary{ctx.ReadBuffer()};
|
||||
|
||||
Tz::Rule rule{};
|
||||
std::memcpy(&rule, binary.data(), sizeof(Tz::Rule));
|
||||
|
||||
u32 count{};
|
||||
std::array<s64, 2> times{};
|
||||
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
|
||||
|
||||
auto res = ToPosixTime(count, times, times_count, calendar, rule);
|
||||
|
||||
ctx.WriteBuffer(times);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar{rp.PopRaw<CalendarTime>()};
|
||||
|
||||
u32 count{};
|
||||
std::array<s64, 2> times{};
|
||||
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
|
||||
|
||||
auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar);
|
||||
|
||||
ctx.WriteBuffer(times);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result TimeZoneService::GetDeviceLocationName(LocationName& out_location_name) {
|
||||
R_RETURN(m_time_zone.GetLocationName(out_location_name));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) {
|
||||
R_RETURN(m_time_zone.GetTotalLocationCount(out_count));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetTimeZoneRuleVersion(RuleVersion& out_rule_version) {
|
||||
R_RETURN(m_time_zone.GetRuleVersion(out_rule_version));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
|
||||
LocationName& location_name) {
|
||||
R_TRY(m_time_zone.GetLocationName(location_name));
|
||||
R_RETURN(m_time_zone.GetTimePoint(out_time_point));
|
||||
}
|
||||
|
||||
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
|
||||
std::span<const u8> binary) {
|
||||
R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
|
||||
R_TRY(m_time_zone.ParseBinary(location_name, binary));
|
||||
|
||||
@ -258,32 +99,67 @@ Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& loca
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TimeZoneService::ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary) {
|
||||
R_RETURN(m_time_zone.ParseBinaryInto(out_rule, binary));
|
||||
Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> binary) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_time_zone.ParseBinaryInto(*out_rule, binary));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule) {
|
||||
R_RETURN(m_time_zone.ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
|
||||
Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info,
|
||||
s64 time) {
|
||||
R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
|
||||
}
|
||||
Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time,
|
||||
InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
|
||||
*out_calendar_time, *out_additional_info);
|
||||
});
|
||||
|
||||
Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times,
|
||||
u32 out_times_count, CalendarTime& calendar_time,
|
||||
Tz::Rule& rule) {
|
||||
R_RETURN(m_time_zone.ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
|
||||
u32 out_times_count, CalendarTime& calendar_time) {
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time));
|
||||
m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get()));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info,
|
||||
s64 time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
|
||||
*out_calendar_time, *out_additional_info);
|
||||
});
|
||||
|
||||
R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const CalendarTime& calendar_time, InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const CalendarTime& calendar_time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time));
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@ -20,45 +21,41 @@ struct Rule;
|
||||
namespace Service::PSC::Time {
|
||||
|
||||
class TimeZoneService final : public ServiceFramework<TimeZoneService> {
|
||||
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
||||
using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
||||
|
||||
public:
|
||||
explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core,
|
||||
TimeZone& time_zone, bool can_write_timezone_device_location);
|
||||
|
||||
~TimeZoneService() override = default;
|
||||
|
||||
Result GetDeviceLocationName(LocationName& out_location_name);
|
||||
Result GetTotalLocationNameCount(u32& out_count);
|
||||
Result GetTimeZoneRuleVersion(RuleVersion& out_rule_version);
|
||||
Result GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
|
||||
LocationName& location_name);
|
||||
Result GetDeviceLocationName(Out<LocationName> out_location_name);
|
||||
Result SetDeviceLocationName(LocationName& location_name);
|
||||
Result GetTotalLocationNameCount(Out<u32> out_count);
|
||||
Result LoadLocationNameList(Out<u32> out_count,
|
||||
OutArray<LocationName, BufferAttr_HipcMapAlias> out_names,
|
||||
u32 index);
|
||||
Result LoadTimeZoneRule(OutRule out_rule, LocationName& location_name);
|
||||
Result GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version);
|
||||
Result GetDeviceLocationNameAndUpdatedTime(Out<LocationName> location_name,
|
||||
Out<SteadyClockTimePoint> out_time_point);
|
||||
Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
|
||||
std::span<const u8> binary);
|
||||
Result ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
|
||||
Result ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar_time, Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar_time);
|
||||
InBuffer<BufferAttr_HipcAutoSelect> binary);
|
||||
Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary);
|
||||
Result GetDeviceLocationNameOperationEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result ToCalendarTime(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule);
|
||||
Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time);
|
||||
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const CalendarTime& calendar_time, InRule rule);
|
||||
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const CalendarTime& calendar_time);
|
||||
|
||||
private:
|
||||
void Handle_GetDeviceLocationName(HLERequestContext& ctx);
|
||||
void Handle_SetDeviceLocationName(HLERequestContext& ctx);
|
||||
void Handle_GetTotalLocationNameCount(HLERequestContext& ctx);
|
||||
void Handle_LoadLocationNameList(HLERequestContext& ctx);
|
||||
void Handle_LoadTimeZoneRule(HLERequestContext& ctx);
|
||||
void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx);
|
||||
void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx);
|
||||
void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx);
|
||||
void Handle_ParseTimeZoneBinary(HLERequestContext& ctx);
|
||||
void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx);
|
||||
void Handle_ToCalendarTime(HLERequestContext& ctx);
|
||||
void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx);
|
||||
void Handle_ToPosixTime(HLERequestContext& ctx);
|
||||
void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
StandardSteadyClockCore& m_clock_core;
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "core/hle/service/set/setting_formats/system_settings.h"
|
||||
|
||||
namespace Service::Set {
|
||||
@ -44,7 +45,7 @@ SystemSettings DefaultSystemSettings() {
|
||||
.console_sleep_plan = ConsoleSleepPlan::Sleep1Hour,
|
||||
};
|
||||
|
||||
settings.device_time_zone_location_name = {"UTC"};
|
||||
settings.device_time_zone_location_name = Service::PSC::Time::LocationName{"UTC"};
|
||||
settings.user_system_clock_automatic_correction_enabled = true;
|
||||
|
||||
settings.primary_album_storage = PrimaryAlbumStorage::SdCard;
|
||||
@ -52,6 +53,17 @@ SystemSettings DefaultSystemSettings() {
|
||||
settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0;
|
||||
settings.vibration_master_volume = 1.0f;
|
||||
|
||||
const auto language_code =
|
||||
available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
|
||||
const auto key_code =
|
||||
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
|
||||
[=](const auto& element) { return element.first == language_code; });
|
||||
|
||||
settings.keyboard_layout = KeyboardLayout::EnglishUs;
|
||||
if (key_code != language_to_layout.end()) {
|
||||
settings.keyboard_layout = key_code->second;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
@ -213,10 +213,9 @@ struct SystemSettings {
|
||||
// nn::settings::system::AudioVolume
|
||||
std::array<u8, 0x8> audio_volume_type0;
|
||||
std::array<u8, 0x8> audio_volume_type1;
|
||||
// nn::settings::system::AudioOutputMode
|
||||
s32 audio_output_mode_type0;
|
||||
s32 audio_output_mode_type1;
|
||||
s32 audio_output_mode_type2;
|
||||
AudioOutputMode audio_output_mode_hdmi;
|
||||
AudioOutputMode audio_output_mode_speaker;
|
||||
AudioOutputMode audio_output_mode_headphone;
|
||||
bool force_mute_on_headphone_removed;
|
||||
INSERT_PADDING_BYTES(0x3);
|
||||
s32 headphone_volume_warning_count;
|
||||
@ -224,9 +223,8 @@ struct SystemSettings {
|
||||
INSERT_PADDING_BYTES(0x3);
|
||||
// nn::settings::system::AudioVolume
|
||||
std::array<u8, 0x8> audio_volume_type2;
|
||||
// nn::settings::system::AudioOutputMode
|
||||
s32 audio_output_mode_type3;
|
||||
s32 audio_output_mode_type4;
|
||||
AudioOutputMode audio_output_mode_type3;
|
||||
AudioOutputMode audio_output_mode_type4;
|
||||
bool hearing_protection_safeguard_flag;
|
||||
INSERT_PADDING_BYTES(0x3);
|
||||
INSERT_PADDING_BYTES(0x4); // Reserved
|
||||
|
@ -23,9 +23,12 @@ enum class AudioOutputMode : u32 {
|
||||
|
||||
/// This is nn::settings::system::AudioOutputModeTarget
|
||||
enum class AudioOutputModeTarget : u32 {
|
||||
None,
|
||||
Hdmi,
|
||||
Speaker,
|
||||
Headphone,
|
||||
Type3,
|
||||
Type4,
|
||||
};
|
||||
|
||||
/// This is nn::settings::system::AudioVolumeTarget
|
||||
@ -367,6 +370,12 @@ struct AccountNotificationSettings {
|
||||
static_assert(sizeof(AccountNotificationSettings) == 0x18,
|
||||
"AccountNotificationSettings is an invalid size");
|
||||
|
||||
/// This is nn::settings::factory::BatteryLot
|
||||
struct BatteryLot {
|
||||
std::array<char, 0x18> lot_number;
|
||||
};
|
||||
static_assert(sizeof(BatteryLot) == 0x18, "BatteryLot is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::EulaVersion
|
||||
struct EulaVersion {
|
||||
u32 version;
|
||||
@ -436,6 +445,12 @@ struct NotificationSettings {
|
||||
};
|
||||
static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size");
|
||||
|
||||
/// This is nn::settings::factory::SerialNumber
|
||||
struct SerialNumber {
|
||||
std::array<char, 0x18> serial_number;
|
||||
};
|
||||
static_assert(sizeof(SerialNumber) == 0x18, "SerialNumber is an invalid size");
|
||||
|
||||
/// This is nn::settings::system::SleepSettings
|
||||
struct SleepSettings {
|
||||
SleepFlag flags;
|
||||
|
@ -25,7 +25,7 @@
|
||||
namespace Service::Set {
|
||||
|
||||
namespace {
|
||||
constexpr u32 SETTINGS_VERSION{1u};
|
||||
constexpr u32 SETTINGS_VERSION{3u};
|
||||
constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
|
||||
struct SettingsHeader {
|
||||
u64 magic;
|
||||
@ -131,10 +131,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
||||
{40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"},
|
||||
{41, nullptr, "GetEdid"},
|
||||
{42, nullptr, "SetEdid"},
|
||||
{43, nullptr, "GetAudioOutputMode"},
|
||||
{44, nullptr, "SetAudioOutputMode"},
|
||||
{45, &ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved, "IsForceMuteOnHeadphoneRemoved"},
|
||||
{46, &ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved, "SetForceMuteOnHeadphoneRemoved"},
|
||||
{43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"},
|
||||
{44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"},
|
||||
{45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"},
|
||||
{46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"},
|
||||
{47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"},
|
||||
{48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"},
|
||||
{49, nullptr, "GetDataDeletionSettings"},
|
||||
@ -155,8 +155,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
||||
{64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"},
|
||||
{65, nullptr, "GetUsb30EnableFlag"},
|
||||
{66, nullptr, "SetUsb30EnableFlag"},
|
||||
{67, nullptr, "GetBatteryLot"},
|
||||
{68, nullptr, "GetSerialNumber"},
|
||||
{67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"},
|
||||
{68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"},
|
||||
{69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"},
|
||||
{70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"},
|
||||
{71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"},
|
||||
@ -184,11 +184,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
||||
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
|
||||
{94, nullptr, "GetFatalDirtyFlags"},
|
||||
{95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
|
||||
{96, nullptr, "SetAutoUpdateEnableFlag"},
|
||||
{96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"},
|
||||
{97, nullptr, "GetNxControllerSettings"},
|
||||
{98, nullptr, "SetNxControllerSettings"},
|
||||
{99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
|
||||
{100, nullptr, "SetBatteryPercentageFlag"},
|
||||
{100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"},
|
||||
{101, nullptr, "GetExternalRtcResetFlag"},
|
||||
{102, nullptr, "SetExternalRtcResetFlag"},
|
||||
{103, nullptr, "GetUsbFullKeyEnableFlag"},
|
||||
@ -208,12 +208,12 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
||||
{117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
|
||||
{118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
|
||||
{119, nullptr, "NeedsToUpdateHeadphoneVolume"},
|
||||
{120, nullptr, "GetPushNotificationActivityModeOnSleep"},
|
||||
{121, nullptr, "SetPushNotificationActivityModeOnSleep"},
|
||||
{120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"},
|
||||
{121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"},
|
||||
{122, nullptr, "GetServiceDiscoveryControlSettings"},
|
||||
{123, nullptr, "SetServiceDiscoveryControlSettings"},
|
||||
{124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
|
||||
{125, nullptr, "SetErrorReportSharePermission"},
|
||||
{125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"},
|
||||
{126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
|
||||
{127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
|
||||
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
|
||||
@ -225,7 +225,7 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
||||
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
|
||||
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
|
||||
{136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"},
|
||||
{137, nullptr, "SetKeyboardLayout"},
|
||||
{137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"},
|
||||
{138, nullptr, "GetWebInspectorFlag"},
|
||||
{139, nullptr, "GetAllowedSslHosts"},
|
||||
{140, nullptr, "GetHostFsMountPoint"},
|
||||
@ -291,8 +291,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
||||
{200, nullptr, "SetButtonConfigRegisteredSettings"},
|
||||
{201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"},
|
||||
{202, nullptr, "SetFieldTestingFlag"},
|
||||
{203, nullptr, "GetPanelCrcMode"},
|
||||
{204, nullptr, "SetPanelCrcMode"},
|
||||
{203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"},
|
||||
{204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"},
|
||||
{205, nullptr, "GetNxControllerSettingsEx"},
|
||||
{206, nullptr, "SetNxControllerSettingsEx"},
|
||||
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
|
||||
@ -349,7 +349,7 @@ bool ISystemSettingsServer::LoadSettingsFile(std::filesystem::path& path, auto&&
|
||||
}
|
||||
SettingsHeader hdr{};
|
||||
file.read(reinterpret_cast<char*>(&hdr), sizeof(hdr));
|
||||
return hdr.magic == SETTINGS_MAGIC && hdr.version == SETTINGS_VERSION;
|
||||
return hdr.magic == SETTINGS_MAGIC && hdr.version >= SETTINGS_VERSION;
|
||||
};
|
||||
|
||||
if (!exists || !file_size_ok) {
|
||||
@ -390,7 +390,7 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto&
|
||||
}
|
||||
|
||||
auto settings_base = path / "settings";
|
||||
auto settings_tmp_file = settings_base;
|
||||
std::filesystem::path settings_tmp_file = settings_base;
|
||||
settings_tmp_file = settings_tmp_file.replace_extension("tmp");
|
||||
std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out);
|
||||
if (!file.is_open()) {
|
||||
@ -817,7 +817,34 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) {
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) {
|
||||
void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto target{rp.PopEnum<AudioOutputModeTarget>()};
|
||||
|
||||
AudioOutputMode output_mode{};
|
||||
const auto result = GetAudioOutputMode(output_mode, target);
|
||||
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(result);
|
||||
rb.PushEnum(output_mode);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto target{rp.PopEnum<AudioOutputModeTarget>()};
|
||||
const auto output_mode{rp.PopEnum<AudioOutputMode>()};
|
||||
|
||||
const auto result = SetAudioOutputMode(target, output_mode);
|
||||
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
|
||||
m_system_settings.force_mute_on_headphone_removed);
|
||||
|
||||
@ -826,7 +853,7 @@ void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx
|
||||
rb.PushRaw(m_system_settings.force_mute_on_headphone_removed);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) {
|
||||
void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>();
|
||||
SetSaveNeeded();
|
||||
@ -969,6 +996,26 @@ void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) {
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) {
|
||||
BatteryLot battery_lot = {"YUZUEMULATOR123456789"};
|
||||
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 8};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(battery_lot);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) {
|
||||
SerialNumber console_serial = {"YUZ10012345678"};
|
||||
|
||||
LOG_INFO(Service_SET, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 8};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(console_serial);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
|
||||
|
||||
@ -1132,6 +1179,17 @@ void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
|
||||
rb.Push(m_system_settings.auto_update_enable_flag);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
m_system_settings.auto_update_enable_flag = rp.Pop<bool>();
|
||||
SetSaveNeeded();
|
||||
|
||||
LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}",
|
||||
m_system_settings.battery_percentage_flag);
|
||||
@ -1141,6 +1199,18 @@ void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
|
||||
rb.Push(m_system_settings.battery_percentage_flag);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
m_system_settings.battery_percentage_flag = rp.Pop<bool>();
|
||||
SetSaveNeeded();
|
||||
|
||||
LOG_INFO(Service_SET, "called, battery_percentage_flag={}",
|
||||
m_system_settings.battery_percentage_flag);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called.");
|
||||
|
||||
@ -1164,6 +1234,27 @@ void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestConte
|
||||
rb.Push(offset);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
|
||||
m_system_settings.push_notification_activity_mode_on_sleep);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(m_system_settings.push_notification_activity_mode_on_sleep);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>();
|
||||
SetSaveNeeded();
|
||||
|
||||
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
|
||||
m_system_settings.push_notification_activity_mode_on_sleep);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
|
||||
m_system_settings.error_report_share_permission);
|
||||
@ -1173,6 +1264,18 @@ void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx
|
||||
rb.PushEnum(m_system_settings.error_report_share_permission);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>();
|
||||
SetSaveNeeded();
|
||||
|
||||
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
|
||||
m_system_settings.error_report_share_permission);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
|
||||
|
||||
@ -1193,22 +1296,22 @@ void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) {
|
||||
const auto language_code =
|
||||
available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
|
||||
const auto key_code =
|
||||
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
|
||||
[=](const auto& element) { return element.first == language_code; });
|
||||
|
||||
KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs;
|
||||
if (key_code != language_to_layout.end()) {
|
||||
selected_keyboard_layout = key_code->second;
|
||||
}
|
||||
|
||||
LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout);
|
||||
LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(static_cast<u32>(selected_keyboard_layout));
|
||||
rb.Push(static_cast<u32>(m_system_settings.keyboard_layout));
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>();
|
||||
SetSaveNeeded();
|
||||
|
||||
LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
|
||||
@ -1300,6 +1403,25 @@ void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) {
|
||||
rb.Push(m_system_settings.field_testing_flag);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(m_system_settings.panel_crc_mode);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
m_system_settings.panel_crc_mode = rp.PopRaw<s32>();
|
||||
SetSaveNeeded();
|
||||
|
||||
LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISystemSettingsServer::SetupSettings() {
|
||||
auto system_dir =
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050";
|
||||
@ -1390,6 +1512,66 @@ Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode,
|
||||
AudioOutputModeTarget target) const {
|
||||
switch (target) {
|
||||
case AudioOutputModeTarget::Hdmi:
|
||||
out_output_mode = m_system_settings.audio_output_mode_hdmi;
|
||||
break;
|
||||
case AudioOutputModeTarget::Speaker:
|
||||
out_output_mode = m_system_settings.audio_output_mode_speaker;
|
||||
break;
|
||||
case AudioOutputModeTarget::Headphone:
|
||||
out_output_mode = m_system_settings.audio_output_mode_headphone;
|
||||
break;
|
||||
case AudioOutputModeTarget::Type3:
|
||||
out_output_mode = m_system_settings.audio_output_mode_type3;
|
||||
break;
|
||||
case AudioOutputModeTarget::Type4:
|
||||
out_output_mode = m_system_settings.audio_output_mode_type4;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
|
||||
}
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
|
||||
AudioOutputMode output_mode) {
|
||||
switch (target) {
|
||||
case AudioOutputModeTarget::Hdmi:
|
||||
m_system_settings.audio_output_mode_hdmi = output_mode;
|
||||
break;
|
||||
case AudioOutputModeTarget::Speaker:
|
||||
m_system_settings.audio_output_mode_speaker = output_mode;
|
||||
break;
|
||||
case AudioOutputModeTarget::Headphone:
|
||||
m_system_settings.audio_output_mode_headphone = output_mode;
|
||||
break;
|
||||
case AudioOutputModeTarget::Type3:
|
||||
m_system_settings.audio_output_mode_type3 = output_mode;
|
||||
break;
|
||||
case AudioOutputModeTarget::Type4:
|
||||
m_system_settings.audio_output_mode_type4 = output_mode;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
|
||||
}
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const {
|
||||
is_auto_mute = m_system_settings.force_mute_on_headphone_removed;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) {
|
||||
m_system_settings.force_mute_on_headphone_removed = is_auto_mute;
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const {
|
||||
out_id = m_private_settings.external_clock_source_id;
|
||||
R_SUCCEED();
|
||||
|
@ -50,6 +50,10 @@ public:
|
||||
|
||||
Result GetVibrationMasterVolume(f32& out_volume) const;
|
||||
Result SetVibrationMasterVolume(f32 volume);
|
||||
Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const;
|
||||
Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode);
|
||||
Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const;
|
||||
Result SetSpeakerAutoMuteFlag(bool auto_mute);
|
||||
Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const;
|
||||
Result SetExternalSteadyClockSourceId(const Common::UUID& id);
|
||||
Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
|
||||
@ -97,8 +101,10 @@ private:
|
||||
void GetSettingsItemValue(HLERequestContext& ctx);
|
||||
void GetTvSettings(HLERequestContext& ctx);
|
||||
void SetTvSettings(HLERequestContext& ctx);
|
||||
void IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
|
||||
void SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
|
||||
void GetAudioOutputMode(HLERequestContext& ctx);
|
||||
void SetAudioOutputMode(HLERequestContext& ctx);
|
||||
void GetSpeakerAutoMuteFlag(HLERequestContext& ctx);
|
||||
void SetSpeakerAutoMuteFlag(HLERequestContext& ctx);
|
||||
void GetDebugModeFlag(HLERequestContext& ctx);
|
||||
void GetQuestFlag(HLERequestContext& ctx);
|
||||
void SetQuestFlag(HLERequestContext& ctx);
|
||||
@ -111,6 +117,8 @@ private:
|
||||
void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
|
||||
void GetPrimaryAlbumStorage(HLERequestContext& ctx);
|
||||
void SetPrimaryAlbumStorage(HLERequestContext& ctx);
|
||||
void GetBatteryLot(HLERequestContext& ctx);
|
||||
void GetSerialNumber(HLERequestContext& ctx);
|
||||
void GetNfcEnableFlag(HLERequestContext& ctx);
|
||||
void SetNfcEnableFlag(HLERequestContext& ctx);
|
||||
void GetSleepSettings(HLERequestContext& ctx);
|
||||
@ -126,13 +134,19 @@ private:
|
||||
void SetBluetoothEnableFlag(HLERequestContext& ctx);
|
||||
void GetMiiAuthorId(HLERequestContext& ctx);
|
||||
void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
|
||||
void SetAutoUpdateEnableFlag(HLERequestContext& ctx);
|
||||
void GetBatteryPercentageFlag(HLERequestContext& ctx);
|
||||
void SetBatteryPercentageFlag(HLERequestContext& ctx);
|
||||
void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
|
||||
void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
|
||||
void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
|
||||
void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
|
||||
void GetErrorReportSharePermission(HLERequestContext& ctx);
|
||||
void SetErrorReportSharePermission(HLERequestContext& ctx);
|
||||
void GetAppletLaunchFlags(HLERequestContext& ctx);
|
||||
void SetAppletLaunchFlags(HLERequestContext& ctx);
|
||||
void GetKeyboardLayout(HLERequestContext& ctx);
|
||||
void SetKeyboardLayout(HLERequestContext& ctx);
|
||||
void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
|
||||
void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
|
||||
void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
|
||||
@ -141,6 +155,8 @@ private:
|
||||
void GetHomeMenuScheme(HLERequestContext& ctx);
|
||||
void GetHomeMenuSchemeModel(HLERequestContext& ctx);
|
||||
void GetFieldTestingFlag(HLERequestContext& ctx);
|
||||
void GetPanelCrcMode(HLERequestContext& ctx);
|
||||
void SetPanelCrcMode(HLERequestContext& ctx);
|
||||
|
||||
bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func);
|
||||
bool StoreSettingsFile(std::filesystem::path& path, auto& settings);
|
||||
|
@ -24,6 +24,7 @@ enum class Errno : u32 {
|
||||
CONNRESET = 104,
|
||||
NOTCONN = 107,
|
||||
TIMEDOUT = 110,
|
||||
CONNREFUSED = 111,
|
||||
INPROGRESS = 115,
|
||||
};
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user