Compare commits

..

6 Commits

Author SHA1 Message Date
82359e986c Android 216 2024-01-28 05:28:41 +00:00
5862b1df55 Merge yuzu-emu#12827 2024-01-28 05:28:41 +00:00
0da5c3912d Merge yuzu-emu#12826 2024-01-28 05:28:41 +00:00
fcae200396 Merge yuzu-emu#12802 2024-01-28 05:28:41 +00:00
ad63c5dc0e Merge yuzu-emu#12760 2024-01-28 05:28:41 +00:00
386bbc6495 Merge yuzu-emu#12749 2024-01-28 05:28:40 +00:00
129 changed files with 2575 additions and 2404 deletions

3
.gitmodules vendored
View File

@ -64,6 +64,3 @@
[submodule "oaknut"] [submodule "oaknut"]
path = externals/oaknut path = externals/oaknut
url = https://github.com/merryhime/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

View File

@ -36,8 +36,6 @@ 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_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_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
@ -310,10 +308,6 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
find_package(Vulkan 1.3.274 REQUIRED) find_package(Vulkan 1.3.274 REQUIRED)
endif() endif()
if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
find_package(VulkanUtilityLibraries REQUIRED)
endif()
if (ENABLE_LIBUSB) if (ENABLE_LIBUSB)
find_package(libusb 1.0.24 MODULE) find_package(libusb 1.0.24 MODULE)
endif() endif()
@ -322,10 +316,6 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
find_package(xbyak 6 CONFIG) find_package(xbyak 6 CONFIG)
endif() endif()
if (ARCHITECTURE_arm64)
find_package(oaknut 2.0.1 CONFIG)
endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
find_package(dynarmic 6.4.0 CONFIG) find_package(dynarmic 6.4.0 CONFIG)
endif() endif()

View File

@ -1,12 +1,10 @@
| Pull Request | Commit | Title | Author | Merged? | | Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----| |----|----|----|----|----|
| [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 | | [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) | [`817d91623`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [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 |
| [12858](https://github.com/yuzu-emu/yuzu-android//pull/12858) | [`5510b3197`](https://github.com/yuzu-emu/yuzu-android//pull/12858/files) | internal_network: only poll for accept on blocking sockets | [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 |
| [12864](https://github.com/yuzu-emu/yuzu-android//pull/12864) | [`9ed82a280`](https://github.com/yuzu-emu/yuzu-android//pull/12864/files) | Small time fixes | [Kelebek1](https://github.com/Kelebek1/) | 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 |
| [12867](https://github.com/yuzu-emu/yuzu-android//pull/12867) | [`a97ecc237`](https://github.com/yuzu-emu/yuzu-android//pull/12867/files) | aoc: fix DLC listing | [liamwhite](https://github.com/liamwhite/) | 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 |
| [12868](https://github.com/yuzu-emu/yuzu-android//pull/12868) | [`e8be665f1`](https://github.com/yuzu-emu/yuzu-android//pull/12868/files) | settings: Allow audio sink, input, and output to be set per game | [t895](https://github.com/t895/) | Yes |
| [12869](https://github.com/yuzu-emu/yuzu-android//pull/12869) | [`acd46c9bd`](https://github.com/yuzu-emu/yuzu-android//pull/12869/files) | SMMU: A set of different fixes. | [FernandoS27](https://github.com/FernandoS27/) | Yes |
End of merge log. You can find the original README.md below the break. End of merge log. You can find the original README.md below the break.

View File

@ -14,17 +14,16 @@ set(BUILD_SHARED_LIBS OFF)
# Skip install rules for all externals # Skip install rules for all externals
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON) set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
# Xbyak (also used by Dynarmic, so needs to be added first) # xbyak
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak) if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
add_subdirectory(xbyak) add_subdirectory(xbyak)
endif() endif()
# Oaknut (also used by Dynarmic, so needs to be added first) # Dynarmic
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut) if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
add_subdirectory(oaknut) add_subdirectory(oaknut)
endif() endif()
# Dynarmic
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic) if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
set(DYNARMIC_IGNORE_ASSERTS ON) set(DYNARMIC_IGNORE_ASSERTS ON)
add_subdirectory(dynarmic) add_subdirectory(dynarmic)
@ -155,11 +154,6 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
add_subdirectory(Vulkan-Headers) add_subdirectory(Vulkan-Headers)
endif() endif()
# Vulkan-Utility-Libraries
if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
add_subdirectory(Vulkan-Utility-Libraries)
endif()
# TZDB (Time Zone Database) # TZDB (Time Zone Database)
add_subdirectory(nx_tzdb) add_subdirectory(nx_tzdb)

View File

@ -1625,11 +1625,11 @@ s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary) {
return 0; return 0;
} }
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep) { bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep) {
return localsub(sp, timep, 0, tmp) == nullptr; return localsub(sp, timep, 0, tmp) == nullptr;
} }
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp) { u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp) {
return time1(out_time, tmp, localsub, sp, 0); return time1(out_time, tmp, localsub, sp, 0);
} }

View File

@ -75,7 +75,7 @@ static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has th
s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary); s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary);
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep); bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep);
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp); u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp);
} // namespace Tz } // namespace Tz

View File

@ -261,7 +261,7 @@ object NativeLibrary {
/** /**
* Begins emulation. * Begins emulation.
*/ */
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean) external fun run(path: String?, programIndex: Int = 0)
// Surface Handling // Surface Handling
external fun surfaceChanged(surf: Surface?) external fun surfaceChanged(surf: Surface?)

View File

@ -7,7 +7,6 @@ import android.text.TextUtils
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding
import org.yuzu.yuzu_emu.features.settings.model.StringSetting import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.model.Driver import org.yuzu.yuzu_emu.model.Driver
@ -58,9 +57,13 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) :
title.text = model.title title.text = model.title
version.text = model.version version.text = model.version
description.text = model.description description.text = model.description
if (model.title != binding.root.context.getString(R.string.system_gpu_driver)) { if (model.description.isNotEmpty()) {
version.visibility = View.VISIBLE
description.visibility = View.VISIBLE
buttonDelete.visibility = View.VISIBLE buttonDelete.visibility = View.VISIBLE
} else { } else {
version.visibility = View.GONE
description.visibility = View.GONE
buttonDelete.visibility = View.GONE buttonDelete.visibility = View.GONE
} }
} }

View File

@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
emulationThread.join() emulationThread.join()
emulationThread = Thread({ emulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.") Log.debug("[EmulationFragment] Starting emulation thread.")
NativeLibrary.run(gamePath, programIndex, false) NativeLibrary.run(gamePath, programIndex)
}, "NativeEmulation") }, "NativeEmulation")
emulationThread.start() emulationThread.start()
} }
@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
State.STOPPED -> { State.STOPPED -> {
emulationThread = Thread({ emulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.") Log.debug("[EmulationFragment] Starting emulation thread.")
NativeLibrary.run(gamePath, programIndex, true) NativeLibrary.run(gamePath, programIndex)
}, "NativeEmulation") }, "NativeEmulation")
emulationThread.start() emulationThread.start()
} }

View File

@ -219,8 +219,7 @@ void EmulationSession::SetAppletId(int applet_id) {
} }
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath, 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); std::scoped_lock lock(m_mutex);
// Create the render window. // Create the render window.
@ -252,8 +251,6 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
// Load the ROM. // Load the ROM.
Service::AM::FrontendAppletParameters params{ Service::AM::FrontendAppletParameters params{
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id), .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), .program_index = static_cast<s32>(program_index),
}; };
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params); m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
@ -450,8 +447,7 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
} }
static Core::SystemResultStatus RunEmulation(const std::string& filepath, static Core::SystemResultStatus RunEmulation(const std::string& filepath,
const size_t program_index, const size_t program_index = 0) {
const bool frontend_initiated) {
MicroProfileOnThreadCreate("EmuThread"); MicroProfileOnThreadCreate("EmuThread");
SCOPE_EXIT({ MicroProfileShutdown(); }); SCOPE_EXIT({ MicroProfileShutdown(); });
@ -464,8 +460,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); 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) { if (result != Core::SystemResultStatus::Success) {
return result; return result;
} }
@ -762,12 +757,10 @@ 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, 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 std::string path = GetJString(env, j_path);
const Core::SystemResultStatus result{ const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
RunEmulation(path, j_program_index, j_frontend_initiated)};
if (result != Core::SystemResultStatus::Success) { if (result != Core::SystemResultStatus::Success) {
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
IDCache::GetExitEmulationActivity(), static_cast<int>(result)); IDCache::GetExitEmulationActivity(), static_cast<int>(result));

View File

@ -47,8 +47,7 @@ public:
void InitializeSystem(bool reload); void InitializeSystem(bool reload);
void SetAppletId(int applet_id); void SetAppletId(int applet_id);
Core::SystemResultStatus InitializeEmulation(const std::string& filepath, Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
const std::size_t program_index, const std::size_t program_index = 0);
const bool frontend_initiated);
bool IsHandheldOnly(); bool IsHandheldOnly();
void SetDeviceType([[maybe_unused]] int index, int type); void SetDeviceType([[maybe_unused]] int index, int type);

View File

@ -210,6 +210,8 @@ add_library(audio_core STATIC
sink/sink_stream.h sink/sink_stream.h
) )
create_target_directory_groups(audio_core)
if (MSVC) if (MSVC)
target_compile_options(audio_core PRIVATE target_compile_options(audio_core PRIVATE
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
@ -265,5 +267,3 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS) if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(audio_core PRIVATE precompiled_headers.h) target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
endif() endif()
create_target_directory_groups(audio_core)

View File

@ -89,13 +89,11 @@ u32 AudioRenderer::Receive(Direction dir) {
} }
void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit, void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, Kernel::KProcess* process, u64 applet_resource_user_id, bool reset) noexcept {
bool reset) noexcept {
command_buffers[session_id].buffer = buffer; command_buffers[session_id].buffer = buffer;
command_buffers[session_id].size = size; command_buffers[session_id].size = size;
command_buffers[session_id].time_limit = time_limit; command_buffers[session_id].time_limit = time_limit;
command_buffers[session_id].applet_resource_user_id = applet_resource_user_id; 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; command_buffers[session_id].reset_buffer = reset;
} }
@ -175,8 +173,7 @@ void AudioRenderer::Main(std::stop_token stop_token) {
// If there are no remaining commands (from the previous list), // If there are no remaining commands (from the previous list),
// this is a new command list, initialize it. // this is a new command list, initialize it.
if (command_buffer.remaining_command_count == 0) { if (command_buffer.remaining_command_count == 0) {
command_list_processor.Initialize(system, *command_buffer.process, command_list_processor.Initialize(system, command_buffer.buffer,
command_buffer.buffer,
command_buffer.size, streams[index]); command_buffer.size, streams[index]);
} }

View File

@ -19,10 +19,6 @@ namespace Core {
class System; class System;
} // namespace Core } // namespace Core
namespace Kernel {
class KProcess;
}
namespace AudioCore { namespace AudioCore {
namespace Sink { namespace Sink {
class Sink; class Sink;
@ -73,8 +69,7 @@ public:
u32 Receive(Direction dir); u32 Receive(Direction dir);
void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit, void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, Kernel::KProcess* process, u64 applet_resource_user_id, bool reset) noexcept;
bool reset) noexcept;
u32 GetRemainCommandCount(s32 session_id) const noexcept; u32 GetRemainCommandCount(s32 session_id) const noexcept;
void ClearRemainCommandCount(s32 session_id) noexcept; void ClearRemainCommandCount(s32 session_id) noexcept;
u64 GetRenderingStartTick(s32 session_id) const noexcept; u64 GetRenderingStartTick(s32 session_id) const noexcept;

View File

@ -6,10 +6,6 @@
#include "audio_core/common/common.h" #include "audio_core/common/common.h"
#include "common/common_types.h" #include "common/common_types.h"
namespace Kernel {
class KProcess;
}
namespace AudioCore::ADSP::AudioRenderer { namespace AudioCore::ADSP::AudioRenderer {
struct CommandBuffer { struct CommandBuffer {
@ -18,7 +14,6 @@ struct CommandBuffer {
u64 size{}; u64 size{};
u64 time_limit{}; u64 time_limit{};
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
Kernel::KProcess* process{};
bool reset_buffer{}; bool reset_buffer{};
// Set by the DSP // Set by the DSP
u32 remaining_command_count{}; u32 remaining_command_count{};

View File

@ -9,15 +9,14 @@
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_process.h"
#include "core/memory.h" #include "core/memory.h"
namespace AudioCore::ADSP::AudioRenderer { namespace AudioCore::ADSP::AudioRenderer {
void CommandListProcessor::Initialize(Core::System& system_, Kernel::KProcess& process, void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
CpuAddr buffer, u64 size, Sink::SinkStream* stream_) { Sink::SinkStream* stream_) {
system = &system_; system = &system_;
memory = &process.GetMemory(); memory = &system->ApplicationMemory();
stream = stream_; stream = stream_;
header = reinterpret_cast<Renderer::CommandListHeader*>(buffer); header = reinterpret_cast<Renderer::CommandListHeader*>(buffer);
commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader)); commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));

View File

@ -16,10 +16,6 @@ class Memory;
class System; class System;
} // namespace Core } // namespace Core
namespace Kernel {
class KProcess;
}
namespace AudioCore { namespace AudioCore {
namespace Sink { namespace Sink {
class SinkStream; class SinkStream;
@ -44,8 +40,7 @@ public:
* @param size - The size of the buffer. * @param size - The size of the buffer.
* @param stream - The stream to be used for sending the samples. * @param stream - The stream to be used for sending the samples.
*/ */
void Initialize(Core::System& system, Kernel::KProcess& process, CpuAddr buffer, u64 size, void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream);
Sink::SinkStream* stream);
/** /**
* Set the maximum processing time for this command list. * Set the maximum processing time for this command list.

View File

@ -6,7 +6,6 @@
#include "audio_core/renderer/audio_renderer.h" #include "audio_core/renderer/audio_renderer.h"
#include "audio_core/renderer/system_manager.h" #include "audio_core/renderer/system_manager.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/audio/errors.h" #include "core/hle/service/audio/errors.h"
@ -18,8 +17,7 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
Result Renderer::Initialize(const AudioRendererParameterInternal& params, Result Renderer::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, Kernel::KTransferMemory* transfer_memory,
const u64 transfer_memory_size, const u32 process_handle, const u64 transfer_memory_size, const u32 process_handle,
Kernel::KProcess& process, const u64 applet_resource_user_id, const u64 applet_resource_user_id, const s32 session_id) {
const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) { if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) { if (!manager.AddSystem(system)) {
LOG_ERROR(Service_Audio, LOG_ERROR(Service_Audio,
@ -30,7 +28,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
} }
initialized = true; initialized = true;
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process, system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
applet_resource_user_id, session_id); applet_resource_user_id, session_id);
return ResultSuccess; return ResultSuccess;

View File

@ -14,8 +14,7 @@ class System;
namespace Kernel { namespace Kernel {
class KTransferMemory; class KTransferMemory;
class KProcess; }
} // namespace Kernel
namespace AudioCore { namespace AudioCore {
struct AudioRendererParameterInternal; struct AudioRendererParameterInternal;
@ -45,8 +44,7 @@ public:
*/ */
Result Initialize(const AudioRendererParameterInternal& params, Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, u32 process_handle, u64 applet_resource_user_id, s32 session_id);
s32 session_id);
/** /**
* Finalize the renderer for shutdown. * Finalize the renderer for shutdown.

View File

@ -32,7 +32,6 @@
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_event.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/hle/kernel/k_transfer_memory.h"
#include "core/memory.h" #include "core/memory.h"
@ -102,8 +101,7 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
Result System::Initialize(const AudioRendererParameterInternal& params, Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle_, Kernel::KProcess& process_, u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) {
u64 applet_resource_user_id_, s32 session_id_) {
if (!CheckValidRevision(params.revision)) { if (!CheckValidRevision(params.revision)) {
return Service::Audio::ResultInvalidRevision; return Service::Audio::ResultInvalidRevision;
} }
@ -119,7 +117,6 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
behavior.SetUserLibRevision(params.revision); behavior.SetUserLibRevision(params.revision);
process_handle = process_handle_; process_handle = process_handle_;
process = &process_;
applet_resource_user_id = applet_resource_user_id_; applet_resource_user_id = applet_resource_user_id_;
session_id = session_id_; session_id = session_id_;
@ -132,7 +129,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device; render_device = params.rendering_device;
execution_mode = params.execution_mode; execution_mode = params.execution_mode;
process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size); core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
// Note: We're not actually using the transfer memory because it's a pain to code for. // 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 // Allocate the memory normally instead and hope the game doesn't try to read anything back
@ -616,8 +613,7 @@ void System::SendCommandToDsp() {
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 * static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))}; (static_cast<f32>(render_time_limit_percent) / 100.0f))};
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit, audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
applet_resource_user_id, process, applet_resource_user_id, reset_command_buffers);
reset_command_buffers);
reset_command_buffers = false; reset_command_buffers = false;
command_buffer_size = command_size; command_buffer_size = command_size;
if (remaining_command_count == 0) { if (remaining_command_count == 0) {

View File

@ -29,7 +29,6 @@ class System;
namespace Kernel { namespace Kernel {
class KEvent; class KEvent;
class KProcess;
class KTransferMemory; class KTransferMemory;
} // namespace Kernel } // namespace Kernel
@ -81,8 +80,7 @@ public:
*/ */
Result Initialize(const AudioRendererParameterInternal& params, Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, u32 process_handle, u64 applet_resource_user_id, s32 session_id);
s32 session_id);
/** /**
* Finalize the system. * Finalize the system.
@ -277,8 +275,6 @@ private:
Common::Event terminate_event{}; Common::Event terminate_event{};
/// Does what locks do /// Does what locks do
std::mutex lock{}; 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 /// Handle for the process for this system, unused
u32 process_handle{}; u32 process_handle{};
/// Applet resource id for this system, unused /// Applet resource id for this system, unused

View File

@ -245,6 +245,8 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
) )
endif() 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 PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
@ -256,5 +258,3 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS) if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(common PRIVATE precompiled_headers.h) target_precompile_headers(common PRIVATE precompiled_headers.h)
endif() endif()
create_target_directory_groups(common)

View File

@ -15,34 +15,25 @@ namespace Common {
#if _MSC_VER #if _MSC_VER
template <typename T> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
[[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 = const u8 result =
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected); _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
return result == expected; return result == expected;
} }
template <> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected) {
const u16 result = const u16 result =
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected); _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
return result == expected; return result == expected;
} }
template <> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected) {
const u32 result = const u32 result =
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected); _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
return result == expected; return result == expected;
} }
template <> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected) {
const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer),
value, expected); value, expected);
return result == expected; return result == expected;
@ -54,32 +45,29 @@ template <>
reinterpret_cast<__int64*>(expected.data())) != 0; reinterpret_cast<__int64*>(expected.data())) != 0;
} }
template <> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected, u8& actual) { u8& actual) {
actual = actual =
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected); _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
return actual == expected; return actual == expected;
} }
template <> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected, u16& actual) {
u16& actual) {
actual = actual =
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected); _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
return actual == expected; return actual == expected;
} }
template <> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected, u32& actual) {
u32& actual) {
actual = actual =
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected); _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
return actual == expected; return actual == expected;
} }
template <> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected, u64& actual) {
u64& actual) {
actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value, actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value,
expected); expected);
return actual == expected; return actual == expected;
@ -103,12 +91,23 @@ template <>
#else #else
template <typename T> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected) {
return __sync_bool_compare_and_swap(pointer, expected, value); return __sync_bool_compare_and_swap(pointer, expected, value);
} }
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected) { [[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) {
unsigned __int128 value_a; unsigned __int128 value_a;
unsigned __int128 expected_a; unsigned __int128 expected_a;
std::memcpy(&value_a, value.data(), sizeof(u128)); std::memcpy(&value_a, value.data(), sizeof(u128));
@ -116,13 +115,31 @@ template <typename T>
return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a); return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
} }
template <typename T> [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual) { u8& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value); actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected; return actual == expected;
} }
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 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,
u128& actual) { u128& actual) {
unsigned __int128 value_a; unsigned __int128 value_a;
unsigned __int128 expected_a; unsigned __int128 expected_a;
@ -134,7 +151,7 @@ template <typename T>
return actual_a == expected_a; return actual_a == expected_a;
} }
[[nodiscard]] inline u128 AtomicLoad128(u64* pointer) { [[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) {
unsigned __int128 zeros_a = 0; unsigned __int128 zeros_a = 0;
unsigned __int128 result_a = unsigned __int128 result_a =
__sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a); __sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);

View File

@ -134,12 +134,12 @@ struct Values {
Linkage linkage{}; Linkage linkage{};
// Audio // Audio
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio,
Category::Audio, Specialization::RuntimeList}; Specialization::RuntimeList};
SwitchableSetting<std::string> audio_output_device_id{ Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio,
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList}; Specialization::RuntimeList};
SwitchableSetting<std::string> audio_input_device_id{ Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio,
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList}; Specialization::RuntimeList};
SwitchableSetting<AudioMode, true> sound_index{ SwitchableSetting<AudioMode, true> sound_index{
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
"sound_index", Category::SystemAudio, Specialization::Default, true, "sound_index", Category::SystemAudio, Specialization::Default, true,

View File

@ -979,6 +979,8 @@ else()
) )
endif() 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 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) target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API)
if (MINGW) if (MINGW)
@ -1056,5 +1058,3 @@ endif()
if (YUZU_ENABLE_LTO) if (YUZU_ENABLE_LTO)
set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif() endif()
create_target_directory_groups(core)

View File

@ -201,22 +201,22 @@ struct System::Impl {
system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true); system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock; 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; 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; 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; 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{}; Service::PSC::Time::LocationName name{};
auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size())); std::memcpy(name.name.data(), new_name.data(), std::min(name.name.size(), new_name.size()));
timezone_service->SetDeviceLocationName(name); timezone_service->SetDeviceLocation(name);
u64 time_offset = 0; u64 time_offset = 0;
if (Settings::values.custom_rtc_enabled) { if (Settings::values.custom_rtc_enabled) {
@ -234,7 +234,7 @@ struct System::Impl {
local_clock->SetCurrentTime(new_time); local_clock->SetCurrentTime(new_time);
network_clock->GetSystemClockContext(&context); network_clock->GetSystemClockContext(context);
settings_service->SetNetworkSystemClockContext(context); settings_service->SetNetworkSystemClockContext(context);
network_clock->SetCurrentTime(new_time); network_clock->SetCurrentTime(new_time);
} }

View File

@ -5,7 +5,6 @@
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <bit>
#include <deque> #include <deque>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -182,28 +181,24 @@ private:
} }
Common::VirtualBuffer<VAddr> cpu_backing_address; Common::VirtualBuffer<VAddr> cpu_backing_address;
using CounterType = u8; static constexpr size_t subentries = 8 / sizeof(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_mask = subentries - 1;
static constexpr size_t subentries_shift =
std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType));
class CounterEntry final { class CounterEntry final {
public: public:
CounterEntry() = default; CounterEntry() = default;
CounterAtomicType& Count(std::size_t page) { std::atomic_uint8_t& Count(std::size_t page) {
return values[page & subentries_mask]; return values[page & subentries_mask];
} }
const CounterAtomicType& Count(std::size_t page) const { const std::atomic_uint8_t& Count(std::size_t page) const {
return values[page & subentries_mask]; return values[page & subentries_mask];
} }
private: private:
std::array<CounterAtomicType, subentries> values{}; std::array<std::atomic_uint8_t, subentries> values{};
}; };
static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType), static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
"CounterEntry should be 8 bytes!"); "CounterEntry should be 8 bytes!");
static constexpr size_t num_counter_entries = static constexpr size_t num_counter_entries =

View File

@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
} }
template <typename Traits> template <typename Traits>
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid, void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
bool track) { Asid asid, bool track) {
Core::Memory::Memory* process_memory = registered_processes[asid.id]; Core::Memory::Memory* process_memory = registered_processes[asid.id];
size_t start_page_d = address >> Memory::YUZU_PAGEBITS; size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
@ -519,36 +519,22 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
size_t page = addr >> Memory::YUZU_PAGEBITS; size_t page = addr >> Memory::YUZU_PAGEBITS;
auto [asid, base_vaddress] = ExtractCPUBacking(page); auto [asid, base_vaddress] = ExtractCPUBacking(page);
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
auto* memory_device_inter = registered_processes[asid.id]; 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) { for (; page != page_end; ++page) {
CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page); std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
auto [asid_2, vpage] = ExtractCPUBacking(page);
vpage >>= Memory::YUZU_PAGEBITS;
if (vpage == 0) [[unlikely]] { if (delta > 0) {
release_pending(); ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
continue; "Count may overflow!");
} } else if (delta < 0) {
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
if (asid.id != asid_2.id) [[unlikely]] { } else {
release_pending(); ASSERT_MSG(false, "Delta must be non-zero!");
memory_device_inter = registered_processes[asid_2.id];
} }
// Adds or subtracts 1, as count is a unsigned 8-bit value // Adds or subtracts 1, as count is a unsigned 8-bit value
count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release); count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
// Assume delta is either -1 or 1 // Assume delta is either -1 or 1
if (count.load(std::memory_order::relaxed) == 0) { if (count.load(std::memory_order::relaxed) == 0) {
@ -567,12 +553,20 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
} }
cache_bytes += Memory::YUZU_PAGESIZE; cache_bytes += Memory::YUZU_PAGESIZE;
} else if (cache_bytes > 0) { } else if (cache_bytes > 0) {
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
cache_bytes, true); true);
cache_bytes = 0; 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 } // namespace Core

View File

@ -543,8 +543,7 @@ void KThread::Unpin() {
ASSERT(m_parent != nullptr); ASSERT(m_parent != nullptr);
// Resume any threads that began waiting on us while we were pinned. // 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(); for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) {
it = m_pinned_waiter_list.erase(it)) {
it->EndWait(ResultSuccess); it->EndWait(ResultSuccess);
} }
} }

View File

@ -303,8 +303,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
} }
// Applet was started by frontend, so it is foreground. // Applet was started by frontend, so it is foreground.
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
applet->focus_state = FocusState::InFocus; applet->focus_state = FocusState::InFocus;
this->InsertApplet(std::move(applet)); this->InsertApplet(std::move(applet));

View File

@ -207,7 +207,7 @@ void Error::Execute() {
void Error::DisplayCompleted() { void Error::DisplayCompleted() {
complete = true; complete = true;
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); PushOutData(std::make_shared<IStorage>(system, std::vector<u8>()));
Exit(); Exit();
} }

View File

@ -85,26 +85,24 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
applet->library_applet_mode = mode; applet->library_applet_mode = mode;
// Set focus state // Set focus state
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
switch (mode) { switch (mode) {
case LibraryAppletMode::AllForeground: case LibraryAppletMode::AllForeground:
case LibraryAppletMode::NoUI: case LibraryAppletMode::NoUI:
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
applet->focus_state = FocusState::InFocus; applet->focus_state = FocusState::InFocus;
applet->hid_registration.EnableAppletToGetInput(true); applet->hid_registration.EnableAppletToGetInput(true);
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
break; break;
case LibraryAppletMode::AllForegroundInitiallyHidden: case LibraryAppletMode::AllForegroundInitiallyHidden:
applet->system_buffer_manager.SetWindowVisibility(false); applet->system_buffer_manager.SetWindowVisibility(false);
applet->focus_state = FocusState::NotInFocus; applet->focus_state = FocusState::NotInFocus;
applet->hid_registration.EnableAppletToGetInput(false); applet->hid_registration.EnableAppletToGetInput(false);
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
break; break;
case LibraryAppletMode::Background: case LibraryAppletMode::Background:
case LibraryAppletMode::BackgroundIndirectDisplay: case LibraryAppletMode::BackgroundIndirectDisplay:
default: default:
applet->focus_state = FocusState::Background; applet->focus_state = FocusState::Background;
applet->hid_registration.EnableAppletToGetInput(true); applet->hid_registration.EnableAppletToGetInput(true);
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
break; break;
} }

View File

@ -202,7 +202,7 @@ void AOC_U::ListAddOnContent(HLERequestContext& ctx) {
LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count,
process_id); process_id);
const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID()); const auto current = system.GetApplicationProcessProgramID();
std::vector<u32> out; std::vector<u32> out;
const auto& disabled = Settings::values.disabled_addons[current]; const auto& disabled = Settings::values.disabled_addons[current];

View File

@ -4,8 +4,6 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/service/audio/audctl.h" #include "core/hle/service/audio/audctl.h"
#include "core/hle/service/ipc_helpers.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 { namespace Service::Audio {
@ -21,15 +19,15 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{6, nullptr, "IsTargetConnected"}, {6, nullptr, "IsTargetConnected"},
{7, nullptr, "SetDefaultTarget"}, {7, nullptr, "SetDefaultTarget"},
{8, nullptr, "GetDefaultTarget"}, {8, nullptr, "GetDefaultTarget"},
{9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"}, {9, nullptr, "GetAudioOutputMode"},
{10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"}, {10, nullptr, "SetAudioOutputMode"},
{11, nullptr, "SetForceMutePolicy"}, {11, nullptr, "SetForceMutePolicy"},
{12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"}, {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
{13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"}, {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
{14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"}, {14, nullptr, "SetOutputModeSetting"},
{15, nullptr, "SetOutputTarget"}, {15, nullptr, "SetOutputTarget"},
{16, nullptr, "SetInputTargetForceEnabled"}, {16, nullptr, "SetInputTargetForceEnabled"},
{17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"}, {17, nullptr, "SetHeadphoneOutputLevelMode"},
{18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"}, {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
@ -42,7 +40,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{27, nullptr, "SetVolumeMappingTableForDev"}, {27, nullptr, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"}, {30, nullptr, "SetSpeakerAutoMuteEnabled"},
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"}, {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"}, {32, nullptr, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"}, {33, nullptr, "GetTargetDeviceInfo"},
@ -70,9 +68,6 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
m_set_sys =
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
} }
AudCtl::~AudCtl() = default; AudCtl::~AudCtl() = default;
@ -101,33 +96,6 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
rb.Push(target_max_volume); 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) { void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
LOG_WARNING(Audio, "(STUBBED) called"); LOG_WARNING(Audio, "(STUBBED) called");
@ -138,31 +106,13 @@ void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) { void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; const auto value = rp.Pop<u32>();
LOG_WARNING(Audio, "(STUBBED) called, target={}", target); LOG_WARNING(Audio, "(STUBBED) called, value={}", value);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushEnum(Set::AudioOutputMode::ch_7_1); rb.PushEnum(AudioOutputMode::PcmAuto);
}
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) { void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
@ -173,28 +123,14 @@ void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
rb.PushEnum(HeadphoneOutputLevelMode::Normal); 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) { void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
bool is_speaker_auto_mute_enabled{}; const bool is_speaker_auto_mute_enabled = false;
const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
is_speaker_auto_mute_enabled); is_speaker_auto_mute_enabled);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result); rb.Push(ResultSuccess);
rb.Push<u8>(is_speaker_auto_mute_enabled); rb.Push<u8>(is_speaker_auto_mute_enabled);
} }

View File

@ -9,10 +9,6 @@ namespace Core {
class System; class System;
} }
namespace Service::Set {
class ISystemSettingsServer;
}
namespace Service::Audio { namespace Service::Audio {
class AudCtl final : public ServiceFramework<AudCtl> { class AudCtl final : public ServiceFramework<AudCtl> {
@ -21,6 +17,14 @@ public:
~AudCtl() override; ~AudCtl() override;
private: private:
enum class AudioOutputMode {
Invalid,
Pcm1ch,
Pcm2ch,
Pcm6ch,
PcmAuto,
};
enum class ForceMutePolicy { enum class ForceMutePolicy {
Disable, Disable,
SpeakerMuteOnHeadphoneUnplugged, SpeakerMuteOnHeadphoneUnplugged,
@ -33,18 +37,10 @@ private:
void GetTargetVolumeMin(HLERequestContext& ctx); void GetTargetVolumeMin(HLERequestContext& ctx);
void GetTargetVolumeMax(HLERequestContext& ctx); void GetTargetVolumeMax(HLERequestContext& ctx);
void GetAudioOutputMode(HLERequestContext& ctx);
void SetAudioOutputMode(HLERequestContext& ctx);
void GetForceMutePolicy(HLERequestContext& ctx); void GetForceMutePolicy(HLERequestContext& ctx);
void GetOutputModeSetting(HLERequestContext& ctx); void GetOutputModeSetting(HLERequestContext& ctx);
void SetOutputModeSetting(HLERequestContext& ctx);
void SetHeadphoneOutputLevelMode(HLERequestContext& ctx);
void GetHeadphoneOutputLevelMode(HLERequestContext& ctx); void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx);
void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx); void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
void AcquireTargetNotification(HLERequestContext& ctx);
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
}; };
} // namespace Service::Audio } // namespace Service::Audio

View File

@ -35,11 +35,10 @@ public:
explicit IAudioRenderer(Core::System& system_, Manager& manager_, explicit IAudioRenderer(Core::System& system_, Manager& manager_,
AudioCore::AudioRendererParameterInternal& params, AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, Kernel::KProcess& process_, u32 process_handle, u64 applet_resource_user_id, s32 session_id)
u64 applet_resource_user_id, s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} { impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
@ -60,15 +59,13 @@ public:
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
process.Open(); impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
applet_resource_user_id, session_id); applet_resource_user_id, session_id);
} }
~IAudioRenderer() override { ~IAudioRenderer() override {
impl->Finalize(); impl->Finalize();
service_context.CloseEvent(rendered_event); service_context.CloseEvent(rendered_event);
process.Close();
} }
private: private:
@ -238,7 +235,6 @@ private:
Kernel::KEvent* rendered_event; Kernel::KEvent* rendered_event;
Manager& manager; Manager& manager;
std::unique_ptr<Renderer> impl; std::unique_ptr<Renderer> impl;
Kernel::KProcess& process;
Common::ScratchBuffer<u8> output_buffer; Common::ScratchBuffer<u8> output_buffer;
Common::ScratchBuffer<u8> performance_buffer; Common::ScratchBuffer<u8> performance_buffer;
}; };
@ -459,7 +455,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
return; return;
} }
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()}; auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
const auto session_id{impl->GetSessionId()}; const auto session_id{impl->GetSessionId()};
@ -476,7 +472,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(), rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
transfer_memory_size, process_handle, *process, transfer_memory_size, process_handle,
applet_resource_user_id, session_id); applet_resource_user_id, session_id);
} }
@ -526,7 +522,7 @@ void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
} }
void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) { void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
LOG_ERROR(Service_Audio, "called. Implement me!"); LOG_DEBUG(Service_Audio, "called");
} }
void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) { void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {

View File

@ -246,10 +246,10 @@ Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
static_service->GetStandardUserSystemClock(&user_clock); static_service->GetStandardUserSystemClock(user_clock);
s64 posix_time{}; s64 posix_time{};
auto result = user_clock->GetCurrentTime(&posix_time); auto result = user_clock->GetCurrentTime(posix_time);
if (result.IsError()) { if (result.IsError()) {
return result; return result;
@ -268,10 +268,10 @@ Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
static_service->GetStandardUserSystemClock(&user_clock); static_service->GetStandardUserSystemClock(user_clock);
s64 posix_time{}; s64 posix_time{};
auto result = user_clock->GetCurrentTime(&posix_time); auto result = user_clock->GetCurrentTime(posix_time);
if (result.IsError()) { if (result.IsError()) {
return result; return result;
@ -470,11 +470,11 @@ AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; 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::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{}; 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 { return {
.year = calendar_time.year, .year = calendar_time.year,

View File

@ -12,109 +12,6 @@
namespace Service { namespace Service {
// clang-format off // 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 { struct RequestLayout {
u32 copy_handle_count; u32 copy_handle_count;
u32 move_handle_count; u32 move_handle_count;
@ -122,14 +19,14 @@ struct RequestLayout {
u32 domain_interface_count; u32 domain_interface_count;
}; };
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0> template <ArgumentType Type1, ArgumentType Type2, typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
constexpr u32 GetInRawDataSize() { constexpr u32 GetArgumentRawDataSize() {
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) { if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
return static_cast<u32>(DataOffset); return static_cast<u32>(DataOffset);
} else { } else {
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InData || ArgumentTraits<ArgType>::Type == ArgumentType::InProcessId) { if constexpr (ArgumentTraits<ArgType>::Type == Type1 || ArgumentTraits<ArgType>::Type == Type2) {
constexpr size_t ArgAlign = alignof(ArgType); constexpr size_t ArgAlign = alignof(ArgType);
constexpr size_t ArgSize = sizeof(ArgType); constexpr size_t ArgSize = sizeof(ArgType);
@ -138,33 +35,9 @@ constexpr u32 GetInRawDataSize() {
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
constexpr size_t ArgEnd = ArgOffset + ArgSize; constexpr size_t ArgEnd = ArgOffset + ArgSize;
return GetInRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>(); return GetArgumentRawDataSize<Type1, Type2, MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
} else { } else {
return GetInRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>(); return GetArgumentRawDataSize<Type1, Type2, 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>();
} }
} }
} }
@ -189,7 +62,7 @@ constexpr RequestLayout GetNonDomainReplyInLayout() {
return RequestLayout{ return RequestLayout{
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
.move_handle_count = 0, .move_handle_count = 0,
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(), .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
.domain_interface_count = 0, .domain_interface_count = 0,
}; };
} }
@ -199,7 +72,7 @@ constexpr RequestLayout GetDomainReplyInLayout() {
return RequestLayout{ return RequestLayout{
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
.move_handle_count = 0, .move_handle_count = 0,
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(), .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
.domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(), .domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(),
}; };
} }
@ -209,7 +82,7 @@ constexpr RequestLayout GetNonDomainReplyOutLayout() {
return RequestLayout{ return RequestLayout{
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(), .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
.domain_interface_count = 0, .domain_interface_count = 0,
}; };
} }
@ -219,7 +92,7 @@ constexpr RequestLayout GetDomainReplyOutLayout() {
return RequestLayout{ return RequestLayout{
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(), .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(),
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(), .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
.domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), .domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
}; };
} }
@ -249,8 +122,6 @@ 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(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment");
static_assert(!RawDataFinished, "All input interface arguments must appear after raw data"); 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 ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
constexpr size_t ArgEnd = ArgOffset + ArgSize; constexpr size_t ArgEnd = ArgOffset + ArgSize;
@ -283,7 +154,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); 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) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
constexpr size_t BufferSize = sizeof(typename ArgType::Type); constexpr size_t BufferSize = sizeof(ArgType);
// Clear the existing data. // Clear the existing data.
std::memset(&std::get<ArgIndex>(args), 0, BufferSize); std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
@ -324,10 +195,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); 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) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
constexpr size_t BufferSize = sizeof(typename ArgType::Type); constexpr size_t BufferSize = sizeof(ArgType);
// Clear the existing data. // Clear the existing data.
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize); std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 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) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
@ -361,40 +232,36 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) { if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
using RawArgType = decltype(std::get<ArgIndex>(args).raw); constexpr size_t ArgAlign = alignof(ArgType);
constexpr size_t ArgAlign = alignof(RawArgType); constexpr size_t ArgSize = sizeof(ArgType);
constexpr size_t ArgSize = sizeof(RawArgType);
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); 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(!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 ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
constexpr size_t ArgEnd = ArgOffset + ArgSize; constexpr size_t ArgEnd = ArgOffset + ArgSize;
std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args).raw, ArgSize); std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize);
return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 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) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) {
if (is_domain) { if (is_domain) {
ctx.AddDomainObject(std::get<ArgIndex>(args).raw); ctx.AddDomainObject(std::get<ArgIndex>(args));
} else { } else {
ctx.AddMoveInterface(std::get<ArgIndex>(args).raw); ctx.AddMoveInterface(std::get<ArgIndex>(args));
} }
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 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) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) {
ctx.AddCopyObject(std::get<ArgIndex>(args).raw); ctx.AddCopyObject(std::get<ArgIndex>(args));
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 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) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) {
ctx.AddMoveObject(std::get<ArgIndex>(args).raw); ctx.AddMoveObject(std::get<ArgIndex>(args));
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 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) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
constexpr size_t BufferSize = sizeof(typename ArgType::Type); constexpr size_t BufferSize = sizeof(ArgType);
ASSERT(ctx.CanWriteBuffer(OutBufferIndex)); ASSERT(ctx.CanWriteBuffer(OutBufferIndex));
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
@ -435,10 +302,10 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
} }
const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false; const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false;
using MethodArguments = std::tuple<std::remove_cvref_t<A>...>; using MethodArguments = std::tuple<std::remove_reference_t<A>...>;
OutTemporaryBuffers buffers{}; OutTemporaryBuffers buffers{};
auto call_arguments = std::tuple<typename UnwrapArg<A>::Type...>(); auto call_arguments = std::tuple<typename RemoveOut<A>::Type...>();
// Read inputs. // Read inputs.
const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2; const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2;

View File

@ -12,31 +12,22 @@
namespace Service { namespace Service {
// clang-format off // clang-format off
template <typename T>
struct AutoOut {
T raw;
};
template <typename T> template <typename T>
class Out { class Out {
public: public:
using Type = T; using Type = T;
/* implicit */ Out(AutoOut<Type>& t) : raw(&t.raw) {} /* implicit */ Out(Type& t) : raw(&t) {}
/* implicit */ Out(Type* t) : raw(t) {} ~Out() = default;
Type* Get() const { Type* Get() const {
return raw; return raw;
} }
Type& operator*() const { Type& operator*() {
return *raw; return *raw;
} }
Type* operator->() const {
return raw;
}
private: private:
Type* raw; Type* raw;
}; };
@ -44,9 +35,6 @@ private:
template <typename T> template <typename T>
using SharedPointer = std::shared_ptr<T>; using SharedPointer = std::shared_ptr<T>;
template <typename T>
using OutInterface = Out<SharedPointer<T>>;
struct ClientProcessId { struct ClientProcessId {
explicit operator bool() const { explicit operator bool() const {
return pid != 0; return pid != 0;
@ -113,21 +101,17 @@ class OutCopyHandle {
public: public:
using Type = T*; using Type = T*;
/* implicit */ OutCopyHandle(AutoOut<Type>& t) : raw(&t.raw) {} /* implicit */ OutCopyHandle(Type& t) : raw(&t) {}
/* implicit */ OutCopyHandle(Type* t) : raw(t) {} ~OutCopyHandle() = default;
Type* Get() const { Type* Get() const {
return raw; return raw;
} }
Type& operator*() const { Type& operator*() {
return *raw; return *raw;
} }
Type* operator->() const {
return raw;
}
private: private:
Type* raw; Type* raw;
}; };
@ -137,34 +121,30 @@ class OutMoveHandle {
public: public:
using Type = T*; using Type = T*;
/* implicit */ OutMoveHandle(AutoOut<Type>& t) : raw(&t.raw) {} /* implicit */ OutMoveHandle(Type& t) : raw(&t) {}
/* implicit */ OutMoveHandle(Type* t) : raw(t) {} ~OutMoveHandle() = default;
Type* Get() const { Type* Get() const {
return raw; return raw;
} }
Type& operator*() const { Type& operator*() {
return *raw; return *raw;
} }
Type* operator->() const {
return raw;
}
private: private:
Type* raw; Type* raw;
}; };
enum BufferAttr : int { enum BufferAttr : int {
/* 0x01 */ BufferAttr_In = (1U << 0), BufferAttr_In = (1U << 0),
/* 0x02 */ BufferAttr_Out = (1U << 1), BufferAttr_Out = (1U << 1),
/* 0x04 */ BufferAttr_HipcMapAlias = (1U << 2), BufferAttr_HipcMapAlias = (1U << 2),
/* 0x08 */ BufferAttr_HipcPointer = (1U << 3), BufferAttr_HipcPointer = (1U << 3),
/* 0x10 */ BufferAttr_FixedSize = (1U << 4), BufferAttr_FixedSize = (1U << 4),
/* 0x20 */ BufferAttr_HipcAutoSelect = (1U << 5), BufferAttr_HipcAutoSelect = (1U << 5),
/* 0x40 */ BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6), BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6),
/* 0x80 */ BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7), BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7),
}; };
template <typename T, int A> template <typename T, int A>
@ -192,79 +172,122 @@ struct Buffer : public std::span<T> {
} }
}; };
template <int A> template <BufferAttr A>
using InBuffer = Buffer<const u8, BufferAttr_In | A>; using InBuffer = Buffer<const u8, BufferAttr_In | A>;
template <typename T, int A> template <typename T, BufferAttr A>
using InArray = Buffer<T, BufferAttr_In | A>; using InArray = Buffer<T, BufferAttr_In | A>;
template <int A> template <BufferAttr A>
using OutBuffer = Buffer<u8, BufferAttr_Out | A>; using OutBuffer = Buffer<u8, BufferAttr_Out | A>;
template <typename T, int A> template <typename T, BufferAttr A>
using OutArray = Buffer<T, BufferAttr_Out | A>; using OutArray = Buffer<T, BufferAttr_Out | A>;
template <typename T, int A> template <typename T, int A>
class InLargeData { struct LargeData : public T {
public:
static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable"); static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
static_assert((A & BufferAttr_Out) == 0, "InLargeData attr must not be Out"); static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize");
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize); static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out");
using Type = const T; static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
using Type = T;
/* implicit */ InLargeData(Type& t) : raw(&t) {} /* implicit */ LargeData(const T& rhs) : T(rhs) {}
~InLargeData() = default; /* implicit */ LargeData() = default;
};
InLargeData& operator=(Type* rhs) { template <typename T, BufferAttr A>
raw = rhs; using InLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_In | A>;
return *this;
}
Type* Get() const { template <typename T, BufferAttr A>
return raw; using OutLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_Out | A>;
}
Type& operator*() const { template <typename T>
return *raw; struct RemoveOut {
} using Type = std::remove_reference_t<T>;
};
Type* operator->() const { template <typename T>
return raw; struct RemoveOut<Out<T>> {
} using Type = typename Out<T>::Type;
};
explicit operator bool() const { template <typename T>
return raw != nullptr; struct RemoveOut<OutCopyHandle<T>> {
} using Type = typename OutCopyHandle<T>::Type;
};
private: template <typename T>
Type* raw; 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> template <typename T, int A>
class OutLargeData { struct ArgumentTraits<Buffer<T, A>> {
public: static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer;
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 */ OutLargeData(Type* t) : raw(t) {} template <typename T, int A>
/* implicit */ OutLargeData(AutoOut<T>& t) : raw(&t.raw) {} struct ArgumentTraits<LargeData<T, A>> {
static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutLargeData : ArgumentType::InLargeData;
};
Type* Get() const { template <typename T>
return raw; struct ArgumentTraits {
} static constexpr ArgumentType Type = ArgumentType::InData;
Type& operator*() const {
return *raw;
}
Type* operator->() const {
return raw;
}
private:
Type* raw;
}; };
// clang-format on // clang-format on

View File

@ -41,7 +41,7 @@ bool AlarmWorker::GetClosestAlarmInfo(Service::PSC::Time::AlarmInfo& out_alarm_i
Service::PSC::Time::AlarmInfo alarm_info{}; Service::PSC::Time::AlarmInfo alarm_info{};
s64 closest_time{}; 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); ASSERT(res == ResultSuccess);
if (is_valid) { if (is_valid) {
@ -76,7 +76,6 @@ void AlarmWorker::OnPowerStateChanged() {
Result AlarmWorker::AttachToClosestAlarmEvent() { Result AlarmWorker::AttachToClosestAlarmEvent() {
m_time_m->GetClosestAlarmUpdatedEvent(&m_event); m_time_m->GetClosestAlarmUpdatedEvent(&m_event);
R_SUCCEED(); R_SUCCEED();
} }

View File

@ -26,7 +26,7 @@ public:
void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m); void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m);
Kernel::KReadableEvent& GetEvent() { Kernel::KEvent& GetEvent() {
return *m_event; return *m_event;
} }
@ -44,7 +44,7 @@ private:
KernelHelpers::ServiceContext m_ctx; KernelHelpers::ServiceContext m_ctx;
std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m; std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m;
Kernel::KReadableEvent* m_event{}; Kernel::KEvent* m_event{};
Kernel::KEvent* m_timer_event{}; Kernel::KEvent* m_timer_event{};
std::shared_ptr<Core::Timing::EventType> m_timer_timing_event; std::shared_ptr<Core::Timing::EventType> m_timer_timing_event;
StandardSteadyClockResource& m_steady_clock_resource; StandardSteadyClockResource& m_steady_clock_resource;

View File

@ -13,8 +13,8 @@ void FileTimestampWorker::SetFilesystemPosixTime() {
Service::PSC::Time::CalendarTime calendar_time{}; Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{}; Service::PSC::Time::CalendarAdditionalInfo additional_info{};
if (m_initialized && m_system_clock->GetCurrentTime(&time) == ResultSuccess && if (m_initialized && m_system_clock->GetCurrentTime(time) == ResultSuccess &&
m_time_zone->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, time) == m_time_zone->ToCalendarTimeWithMyRule(calendar_time, additional_info, time) ==
ResultSuccess) { ResultSuccess) {
// TODO IFileSystemProxy::SetCurrentPosixTime // TODO IFileSystemProxy::SetCurrentPosixTime
} }

View File

@ -79,18 +79,18 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN
auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
Service::PSC::Time::LocationName configured_name{}; Service::PSC::Time::LocationName configured_name{};
std::memcpy(configured_name.data(), configured_zone.data(), std::memcpy(configured_name.name.data(), configured_zone.data(),
std::min(configured_name.size(), configured_zone.size())); std::min(configured_name.name.size(), configured_zone.size()));
if (!IsTimeZoneBinaryValid(configured_name)) { if (!IsTimeZoneBinaryValid(configured_name)) {
configured_zone = Common::TimeZone::FindSystemTimeZone(); configured_zone = Common::TimeZone::FindSystemTimeZone();
configured_name = {}; configured_name = {};
std::memcpy(configured_name.data(), configured_zone.data(), std::memcpy(configured_name.name.data(), configured_zone.data(),
std::min(configured_name.size(), configured_zone.size())); std::min(configured_name.name.size(), configured_zone.size()));
} }
ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!", ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!",
configured_name.data()); configured_name.name.data());
return configured_name; return configured_name;
} }
@ -103,7 +103,7 @@ TimeManager::TimeManager(Core::System& system)
m_time_m = m_time_m =
system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true); 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); ASSERT(res == ResultSuccess);
m_set_sys = m_set_sys =
@ -114,10 +114,10 @@ TimeManager::TimeManager(Core::System& system)
m_worker.Initialize(m_time_sm, m_set_sys); 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); 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); ASSERT(res == ResultSuccess);
res = SetupStandardSteadyClockCore(); res = SetupStandardSteadyClockCore();
@ -161,8 +161,8 @@ TimeManager::TimeManager(Core::System& system)
automatic_correction_time_point); automatic_correction_time_point);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled, res = m_time_m->SetupStandardUserSystemClockCore(automatic_correction_time_point,
automatic_correction_time_point); is_automatic_correction_enabled);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
res = m_time_m->SetupEphemeralNetworkSystemClockCore(); res = m_time_m->SetupEphemeralNetworkSystemClockCore();
@ -184,12 +184,12 @@ TimeManager::TimeManager(Core::System& system)
m_file_timestamp_worker.m_initialized = true; m_file_timestamp_worker.m_initialized = true;
s64 system_clock_time{}; 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) { ResultSuccess) {
Service::PSC::Time::CalendarTime calendar_time{}; Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo calendar_additional{}; Service::PSC::Time::CalendarAdditionalInfo calendar_additional{};
if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule( 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, // TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time,
// calendar_additional.ut_offset) // calendar_additional.ut_offset)
} }
@ -228,9 +228,10 @@ Result TimeManager::SetupStandardSteadyClockCore() {
m_set_sys->SetExternalSteadyClockSourceId(clock_source_id); m_set_sys->SetExternalSteadyClockSourceId(clock_source_id);
} }
res = m_time_m->SetupStandardSteadyClockCore( res = m_time_m->SetupStandardSteadyClockCore(clock_source_id, m_steady_clock_resource.GetTime(),
reset_detected, clock_source_id, m_steady_clock_resource.GetTime(), external_steady_clock_internal_offset_ns,
external_steady_clock_internal_offset_ns, standard_steady_clock_test_offset_ns); standard_steady_clock_test_offset_ns,
reset_detected);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
R_SUCCEED(); R_SUCCEED();
} }
@ -242,15 +243,14 @@ Result TimeManager::SetupTimeZoneServiceCore() {
auto configured_zone = GetTimeZoneString(name); auto configured_zone = GetTimeZoneString(name);
if (configured_zone != name) { if (configured_zone.name != name.name) {
m_set_sys->SetDeviceTimeZoneLocationName(configured_zone); m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
name = configured_zone; name = configured_zone;
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; 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{}; Service::PSC::Time::SystemClockContext context{};
local_clock->GetSystemClockContext(&context); local_clock->GetSystemClockContext(context);
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point); m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point);
} }
@ -267,7 +267,7 @@ Result TimeManager::SetupTimeZoneServiceCore() {
res = GetTimeZoneRule(rule_buffer, rule_size, name); res = GetTimeZoneRule(rule_buffer, rule_size, name);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point, res = m_time_m->SetupTimeZoneServiceCore(name, time_point, rule_version, location_count,
rule_buffer); rule_buffer);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);

View File

@ -3,11 +3,9 @@
#include <chrono> #include <chrono>
#include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/svc.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/file_timestamp_worker.h"
#include "core/hle/service/glue/time/static.h" #include "core/hle/service/glue/time/static.h"
#include "core/hle/service/psc/time/errors.h" #include "core/hle/service/psc/time/errors.h"
@ -43,25 +41,25 @@ StaticService::StaticService(Core::System& system_,
time->m_steady_clock_resource} { time->m_steady_clock_resource} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"}, {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"},
{1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"}, {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
{2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"}, {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"},
{3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"}, {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"},
{4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"}, {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
{5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"}, {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"},
{20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
{50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"}, {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"},
{51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"}, {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"},
{100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
{101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
{102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"}, {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"},
{200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"}, {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
{201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
{300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"}, {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
{400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"}, {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"},
{401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"}, {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
{500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"}, {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
{501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"}, {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"},
}; };
// clang-format on // clang-format on
@ -73,80 +71,314 @@ StaticService::StaticService(Core::System& system_,
if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock && 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_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_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 && } 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_network_clock &&
!m_setup_info.can_write_timezone_device_location && !m_setup_info.can_write_timezone_device_location &&
!m_setup_info.can_write_steady_clock && !m_setup_info.can_write_steady_clock &&
!m_setup_info.can_write_uninitialized_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 && } 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_network_clock &&
!m_setup_info.can_write_timezone_device_location && !m_setup_info.can_write_timezone_device_location &&
m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { 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 { } else {
UNREACHABLE(); UNREACHABLE();
} }
auto res = m_wrapped_service->GetTimeZoneService(&m_time_zone); auto res = m_wrapped_service->GetTimeZoneService(m_time_zone);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
} }
Result StaticService::GetStandardUserSystemClock( void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
OutInterface<Service::PSC::Time::SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called."); 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) {
R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service)); R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service));
} }
Result StaticService::GetStandardNetworkSystemClock( Result StaticService::GetStandardNetworkSystemClock(
OutInterface<Service::PSC::Time::SystemClock> out_service) { std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service)); R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service));
} }
Result StaticService::GetStandardSteadyClock( Result StaticService::GetStandardSteadyClock(
OutInterface<Service::PSC::Time::SteadyClock> out_service) { std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service)); R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service));
} }
Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) { Result StaticService::GetTimeZoneService(std::shared_ptr<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,
*out_service = std::make_shared<TimeZoneService>( m_time_zone);
m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location,
m_time_zone);
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetStandardLocalSystemClock( Result StaticService::GetStandardLocalSystemClock(
OutInterface<Service::PSC::Time::SystemClock> out_service) { std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service)); R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service));
} }
Result StaticService::GetEphemeralNetworkSystemClock( Result StaticService::GetEphemeralNetworkSystemClock(
OutInterface<Service::PSC::Time::SystemClock> out_service) { std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service)); R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service));
} }
Result StaticService::GetSharedMemoryNativeHandle( Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory)); R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory));
} }
Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { 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_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied);
R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset( R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset(
@ -154,92 +386,62 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count())); std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()));
} }
Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { Result StaticService::GetStandardSteadyClockRtcValue(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));
R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value));
} }
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
Out<bool> out_automatic_correction) { bool& out_automatic_correction) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction);
});
R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled( R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled(
out_automatic_correction)); out_automatic_correction));
} }
Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
bool automatic_correction) { bool automatic_correction) {
LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled( R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled(
automatic_correction)); automatic_correction));
} }
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { Result StaticService::GetStandardUserSystemClockInitialYear(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");
*out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(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)); R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient));
} }
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { 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( R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
out_time_point)); out_time_point));
} }
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(
Out<s64> out_time, Service::PSC::Time::SystemClockContext& context) { 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)); R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context));
} }
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, Result StaticService::GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::TimeType type) { 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)); R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type));
} }
Result StaticService::GetClockSnapshotFromSystemClockContext( Result StaticService::GetClockSnapshotFromSystemClockContext(
Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::SystemClockContext& user_context, Service::PSC::Time::SystemClockContext& user_context,
Service::PSC::Time::SystemClockContext& network_context) { Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type) {
SCOPE_EXIT({ R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(out_snapshot, user_context,
LOG_DEBUG(Service_Time, network_context, type));
"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(Out<s64> out_time, Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(
InClockSnapshot a, s64& out_time, Service::PSC::Time::ClockSnapshot& a, Service::PSC::Time::ClockSnapshot& b) {
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)); R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b));
} }
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, Result StaticService::CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a,
InClockSnapshot b) { Service::PSC::Time::ClockSnapshot& 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)); R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b));
} }

View File

@ -4,7 +4,6 @@
#pragma once #pragma once
#include "common/common_types.h" #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/manager.h"
#include "core/hle/service/glue/time/time_zone.h" #include "core/hle/service/glue/time/time_zone.h"
#include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/common.h"
@ -30,10 +29,6 @@ class FileTimestampWorker;
class StandardSteadyClockResource; class StandardSteadyClockResource;
class StaticService final : public ServiceFramework<StaticService> { 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: public:
explicit StaticService(Core::System& system, explicit StaticService(Core::System& system,
Service::PSC::Time::StaticServiceSetupInfo setup_info, Service::PSC::Time::StaticServiceSetupInfo setup_info,
@ -41,34 +36,65 @@ public:
~StaticService() override = default; ~StaticService() override = default;
Result GetStandardUserSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); Result GetStandardUserSystemClock(
Result GetStandardNetworkSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
Result GetStandardSteadyClock(OutInterface<Service::PSC::Time::SteadyClock> out_service); Result GetStandardNetworkSystemClock(
Result GetTimeZoneService(OutInterface<TimeZoneService> out_service); std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
Result GetStandardLocalSystemClock(OutInterface<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 GetEphemeralNetworkSystemClock( Result GetEphemeralNetworkSystemClock(
OutInterface<Service::PSC::Time::SystemClock> out_service); std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory);
Result SetStandardSteadyClockInternalOffset(s64 offset_ns); Result SetStandardSteadyClockInternalOffset(s64 offset);
Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value); Result GetStandardSteadyClockRtcValue(s64& out_rtc_value);
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled); Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_automatic_correction);
Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
Result GetStandardUserSystemClockInitialYear(Out<s32> out_year); Result GetStandardUserSystemClockInitialYear(s32& out_year);
Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient); Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient);
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); Service::PSC::Time::SteadyClockTimePoint& out_time_point);
Result CalculateMonotonicSystemClockBaseTimePoint( Result CalculateMonotonicSystemClockBaseTimePoint(
Out<s64> out_time, Service::PSC::Time::SystemClockContext& context); s64& out_time, Service::PSC::Time::SystemClockContext& context);
Result GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type); Result GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::TimeType type);
Result GetClockSnapshotFromSystemClockContext( Result GetClockSnapshotFromSystemClockContext(
Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::SystemClockContext& user_context, Service::PSC::Time::SystemClockContext& user_context,
Service::PSC::Time::SystemClockContext& network_context); Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type);
Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time,
InClockSnapshot a, InClockSnapshot b); Service::PSC::Time::ClockSnapshot& a,
Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); Service::PSC::Time::ClockSnapshot& b);
Result CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a,
Service::PSC::Time::ClockSnapshot& b);
private: 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; Core::System& m_system;
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;

View File

@ -3,10 +3,8 @@
#include <chrono> #include <chrono>
#include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/svc.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/file_timestamp_worker.h"
#include "core/hle/service/glue/time/time_zone.h" #include "core/hle/service/glue/time/time_zone.h"
#include "core/hle/service/glue/time/time_zone_binary.h" #include "core/hle/service/glue/time/time_zone_binary.h"
@ -30,20 +28,20 @@ TimeZoneService::TimeZoneService(
m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} { m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"}, {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"},
{1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"}, {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"},
{2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"}, {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"},
{3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"}, {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"},
{4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"}, {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"},
{5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"}, {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
{6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"}, {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"},
{7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"}, {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"},
{8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"}, {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"},
{20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"}, {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"},
{100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"}, {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"},
{101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"}, {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
{201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"}, {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"},
{202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"}, {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
@ -55,16 +53,220 @@ TimeZoneService::TimeZoneService(
TimeZoneService::~TimeZoneService() = default; TimeZoneService::~TimeZoneService() = default;
Result TimeZoneService::GetDeviceLocationName( void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) {
Out<Service::PSC::Time::LocationName> out_location_name) { LOG_DEBUG(Service_Time, "called.");
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)); R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name));
} }
Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName& location_name) { Result TimeZoneService::SetDeviceLocation(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(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound); R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound);
@ -80,7 +282,7 @@ Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName&
Service::PSC::Time::SteadyClockTimePoint time_point{}; Service::PSC::Time::SteadyClockTimePoint time_point{};
Service::PSC::Time::LocationName name{}; Service::PSC::Time::LocationName name{};
R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(&name, &time_point)); R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(time_point, name));
m_set_sys->SetDeviceTimeZoneLocationName(name); m_set_sys->SetDeviceTimeZoneLocationName(name);
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point); m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point);
@ -92,27 +294,19 @@ Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName&
R_SUCCEED(); R_SUCCEED();
} }
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count)); R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count));
} }
Result TimeZoneService::LoadLocationNameList( Result TimeZoneService::LoadLocationNameList(
Out<u32> out_count, u32& out_count, std::vector<Service::PSC::Time::LocationName>& out_names, size_t max_names,
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { 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}; std::scoped_lock l{m_mutex};
R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index)); R_RETURN(GetTimeZoneLocationList(out_count, out_names, max_names, index));
} }
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& name) { Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule,
LOG_DEBUG(Service_Time, "called. name={}", name); Service::PSC::Time::LocationName& name) {
std::scoped_lock l{m_mutex}; std::scoped_lock l{m_mutex};
std::span<const u8> binary{}; std::span<const u8> binary{};
size_t binary_size{}; size_t binary_size{};
@ -120,43 +314,23 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::L
R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary)); R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
} }
Result TimeZoneService::GetTimeZoneRuleVersion( Result TimeZoneService::GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version) {
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)); R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version));
} }
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
Out<Service::PSC::Time::LocationName> location_name, Service::PSC::Time::SteadyClockTimePoint& out_time_point,
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { Service::PSC::Time::LocationName& location_name) {
SCOPE_EXIT({ R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(out_time_point, location_name));
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_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
R_RETURN(Service::PSC::Time::ResultNotImplemented); 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( Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
OutCopyHandle<Kernel::KReadableEvent> out_event) { Kernel::KEvent** out_event) {
LOG_DEBUG(Service_Time, "called.");
if (!operation_event_initialized) { if (!operation_event_initialized) {
operation_event_initialized = false; operation_event_initialized = false;
@ -168,56 +342,36 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
g_list_nodes.push_back(m_operation_event); g_list_nodes.push_back(m_operation_event);
} }
*out_event = &m_operation_event.m_event->GetReadableEvent(); *out_event = m_operation_event.m_event;
R_SUCCEED(); R_SUCCEED();
} }
Result TimeZoneService::ToCalendarTime( Result TimeZoneService::ToCalendarTime(
Out<Service::PSC::Time::CalendarTime> out_calendar_time, Service::PSC::Time::CalendarTime& out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) { Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& 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)); R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
} }
Result TimeZoneService::ToCalendarTimeWithMyRule( Result TimeZoneService::ToCalendarTimeWithMyRule(
Out<Service::PSC::Time::CalendarTime> out_calendar_time, Service::PSC::Time::CalendarTime& out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) { 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( R_RETURN(
m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
} }
Result TimeZoneService::ToPosixTime(Out<u32> out_count, Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times,
OutArray<s64, BufferAttr_HipcPointer> out_times, u32 out_times_count,
const Service::PSC::Time::CalendarTime& calendar_time, Service::PSC::Time::CalendarTime& calendar_time,
InRule rule) { Tz::Rule& rule) {
SCOPE_EXIT({ R_RETURN(
LOG_DEBUG(Service_Time, m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
"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( Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, u32 out_times_count,
const Service::PSC::Time::CalendarTime& calendar_time) { Service::PSC::Time::CalendarTime& calendar_time) {
SCOPE_EXIT({ R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count,
LOG_DEBUG(Service_Time, calendar_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 } // namespace Service::Glue::Time

View File

@ -8,7 +8,6 @@
#include <span> #include <span>
#include <vector> #include <vector>
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/common.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
@ -34,9 +33,6 @@ namespace Service::Glue::Time {
class FileTimestampWorker; class FileTimestampWorker;
class TimeZoneService final : public ServiceFramework<TimeZoneService> { class TimeZoneService final : public ServiceFramework<TimeZoneService> {
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
public: public:
explicit TimeZoneService( explicit TimeZoneService(
Core::System& system, FileTimestampWorker& file_timestamp_worker, Core::System& system, FileTimestampWorker& file_timestamp_worker,
@ -45,35 +41,46 @@ public:
~TimeZoneService() override; ~TimeZoneService() override;
Result GetDeviceLocationName(Out<Service::PSC::Time::LocationName> out_location_name); Result GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name);
Result SetDeviceLocationName(Service::PSC::Time::LocationName& location_name); Result SetDeviceLocation(Service::PSC::Time::LocationName& location_name);
Result GetTotalLocationNameCount(Out<u32> out_count); Result GetTotalLocationNameCount(u32& out_count);
Result LoadLocationNameList( Result LoadLocationNameList(u32& out_count,
Out<u32> out_count, std::vector<Service::PSC::Time::LocationName>& out_names,
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index); size_t max_names, u32 index);
Result LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& location_name); Result LoadTimeZoneRule(Tz::Rule& out_rule, Service::PSC::Time::LocationName& name);
Result GetTimeZoneRuleVersion(Out<Service::PSC::Time::RuleVersion> out_rule_version); Result GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version);
Result GetDeviceLocationNameAndUpdatedTime( Result GetDeviceLocationNameAndUpdatedTime(
Out<Service::PSC::Time::LocationName> location_name, Service::PSC::Time::SteadyClockTimePoint& out_time_point,
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); Service::PSC::Time::LocationName& location_name);
Result SetDeviceLocationNameWithTimeZoneRule(Service::PSC::Time::LocationName& location_name, Result SetDeviceLocationNameWithTimeZoneRule();
InBuffer<BufferAttr_HipcAutoSelect> binary); Result GetDeviceLocationNameOperationEventReadableHandle(Kernel::KEvent** out_event);
Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); Result ToCalendarTime(Service::PSC::Time::CalendarTime& out_calendar_time,
Result GetDeviceLocationNameOperationEventReadableHandle( Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time,
OutCopyHandle<Kernel::KReadableEvent> out_event); Tz::Rule& rule);
Result ToCalendarTime(Out<Service::PSC::Time::CalendarTime> out_calendar_time, Result ToCalendarTimeWithMyRule(Service::PSC::Time::CalendarTime& out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, Service::PSC::Time::CalendarAdditionalInfo& out_additional_info,
s64 time, InRule rule); s64 time);
Result ToCalendarTimeWithMyRule( Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
Out<Service::PSC::Time::CalendarTime> out_calendar_time, Service::PSC::Time::CalendarTime& calendar_time, Tz::Rule& rule);
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time); Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, Service::PSC::Time::CalendarTime& calendar_time);
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: 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; Core::System& m_system;
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;

View File

@ -103,7 +103,7 @@ void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName
return; return;
} }
// out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name); // out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name);
out_path = fmt::format("/zoneinfo/{}", name.data()); out_path = fmt::format("/zoneinfo/{}", name.name.data());
} }
bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) { 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, Result GetTimeZoneLocationList(u32& out_count,
std::span<Service::PSC::Time::LocationName> out_names, std::vector<Service::PSC::Time::LocationName>& out_names,
size_t max_names, u32 index) { size_t max_names, u32 index) {
std::string path{}; std::string path{};
GetTimeZoneBinaryListPath(path); GetTimeZoneBinaryListPath(path);
@ -193,7 +193,7 @@ Result GetTimeZoneLocationList(u32& out_count,
if (chr == '\n') { if (chr == '\n') {
if (name_count >= index) { if (name_count >= index) {
out_names[out_count] = current_name; out_names.push_back(current_name);
out_count++; out_count++;
if (out_count >= max_names) { if (out_count >= max_names) {
break; break;
@ -209,9 +209,10 @@ Result GetTimeZoneLocationList(u32& out_count,
break; break;
} }
R_UNLESS(current_name_len <= current_name.size() - 2, Service::PSC::Time::ResultFailed); R_UNLESS(current_name_len <= current_name.name.size() - 2,
Service::PSC::Time::ResultFailed);
current_name[current_name_len++] = chr; current_name.name[current_name_len++] = chr;
} }
R_SUCCEED(); R_SUCCEED();

View File

@ -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, Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
Service::PSC::Time::LocationName& name); Service::PSC::Time::LocationName& name);
Result GetTimeZoneLocationList(u32& out_count, Result GetTimeZoneLocationList(u32& out_count,
std::span<Service::PSC::Time::LocationName> out_names, std::vector<Service::PSC::Time::LocationName>& out_names,
size_t max_names, u32 index); size_t max_names, u32 index);
} // namespace Service::Glue::Time } // namespace Service::Glue::Time

View File

@ -38,12 +38,11 @@ T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
FileTimestampWorker& file_timestamp_worker) FileTimestampWorker& file_timestamp_worker)
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent( : m_system{system}, m_ctx{m_system, "Glue:58"}, m_event{m_ctx.CreateEvent("Glue:58:Event")},
"Glue:TimeWorker:Event")},
m_steady_clock_resource{steady_clock_resource}, m_steady_clock_resource{steady_clock_resource},
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent( m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent(
"Glue:TimeWorker:SteadyClockTimerEvent")}, "Glue:58:SteadyClockTimerEvent")},
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")}, m_timer_file_system{m_ctx.CreateEvent("Glue:58:FileTimeTimerEvent")},
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} { 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_ig_report_network_clock_context_set = false;
g_report_network_clock_context = {}; g_report_network_clock_context = {};
@ -114,17 +113,17 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t
std::chrono::nanoseconds(fs_notify_time_ns), std::chrono::nanoseconds(fs_notify_time_ns),
m_timer_file_system_timing_event); 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); ASSERT(res == ResultSuccess);
res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event); res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
res = m_time_sm->GetStandardNetworkSystemClock(&m_network_clock); res = m_time_sm->GetStandardNetworkSystemClock(m_network_clock);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event); res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
res = m_time_sm->GetEphemeralNetworkSystemClock(&m_ephemeral_clock); res = m_time_sm->GetEphemeralNetworkSystemClock(m_ephemeral_clock);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
res = res =
m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event); m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event);
@ -184,19 +183,22 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
// TODO // TODO
// AddWaiter(gIPmModuleService::GetEvent(), 1); // AddWaiter(gIPmModuleService::GetEvent(), 1);
AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange); AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange);
} else { } else {
AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
// TODO // TODO
// AddWaiter(gIPmModuleService::GetEvent(), 1); // AddWaiter(gIPmModuleService::GetEvent(), 1);
AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange); AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange);
AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms); AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms);
AddWaiter(m_local_clock_event, EventType::UpdateLocalSystemClock); AddWaiter(&m_local_clock_event->GetReadableEvent(), EventType::UpdateLocalSystemClock);
AddWaiter(m_network_clock_event, EventType::UpdateNetworkSystemClock); AddWaiter(&m_network_clock_event->GetReadableEvent(),
AddWaiter(m_ephemeral_clock_event, EventType::UpdateEphemeralSystemClock); EventType::UpdateNetworkSystemClock);
AddWaiter(&m_ephemeral_clock_event->GetReadableEvent(),
EventType::UpdateEphemeralSystemClock);
AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock); AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock);
AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp); AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp);
AddWaiter(m_standard_user_auto_correct_clock_event, EventType::AutoCorrect); AddWaiter(&m_standard_user_auto_correct_clock_event->GetReadableEvent(),
EventType::AutoCorrect);
} }
s32 out_index{-1}; s32 out_index{-1};
@ -235,7 +237,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
m_local_clock_event->Clear(); m_local_clock_event->Clear();
Service::PSC::Time::SystemClockContext context{}; Service::PSC::Time::SystemClockContext context{};
auto res = m_local_clock->GetSystemClockContext(&context); auto res = m_local_clock->GetSystemClockContext(context);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
m_set_sys->SetUserSystemClockContext(context); m_set_sys->SetUserSystemClockContext(context);
@ -246,12 +248,12 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
case EventType::UpdateNetworkSystemClock: { case EventType::UpdateNetworkSystemClock: {
m_network_clock_event->Clear(); m_network_clock_event->Clear();
Service::PSC::Time::SystemClockContext context{}; Service::PSC::Time::SystemClockContext context{};
auto res = m_network_clock->GetSystemClockContext(&context); auto res = m_network_clock->GetSystemClockContext(context);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
m_set_sys->SetNetworkSystemClockContext(context); m_set_sys->SetNetworkSystemClockContext(context);
s64 time{}; s64 time{};
if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) { if (m_network_clock->GetCurrentTime(time) != ResultSuccess) {
break; break;
} }
@ -273,13 +275,13 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
m_ephemeral_clock_event->Clear(); m_ephemeral_clock_event->Clear();
Service::PSC::Time::SystemClockContext context{}; Service::PSC::Time::SystemClockContext context{};
auto res = m_ephemeral_clock->GetSystemClockContext(&context); auto res = m_ephemeral_clock->GetSystemClockContext(context);
if (res != ResultSuccess) { if (res != ResultSuccess) {
break; break;
} }
s64 time{}; s64 time{};
res = m_ephemeral_clock->GetCurrentTime(&time); res = m_ephemeral_clock->GetCurrentTime(time);
if (res != ResultSuccess) { if (res != ResultSuccess) {
break; break;
} }
@ -315,11 +317,11 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
bool automatic_correction{}; bool automatic_correction{};
auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled(
&automatic_correction); automatic_correction);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
Service::PSC::Time::SteadyClockTimePoint time_point{}; Service::PSC::Time::SteadyClockTimePoint time_point{};
res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point); res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
ASSERT(res == ResultSuccess); ASSERT(res == ResultSuccess);
m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction); m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction);

View File

@ -49,10 +49,10 @@ private:
std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock; std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock;
StandardSteadyClockResource& m_steady_clock_resource; StandardSteadyClockResource& m_steady_clock_resource;
FileTimestampWorker& m_file_timestamp_worker; FileTimestampWorker& m_file_timestamp_worker;
Kernel::KReadableEvent* m_local_clock_event{}; Kernel::KEvent* m_local_clock_event{};
Kernel::KReadableEvent* m_network_clock_event{}; Kernel::KEvent* m_network_clock_event{};
Kernel::KReadableEvent* m_ephemeral_clock_event{}; Kernel::KEvent* m_ephemeral_clock_event{};
Kernel::KReadableEvent* m_standard_user_auto_correct_clock_event{}; Kernel::KEvent* m_standard_user_auto_correct_clock_event{};
Kernel::KEvent* m_timer_steady_clock{}; Kernel::KEvent* m_timer_steady_clock{};
std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event; std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event;
Kernel::KEvent* m_timer_file_system{}; Kernel::KEvent* m_timer_file_system{};

View File

@ -8,7 +8,6 @@
#include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/kernel/kernel.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/hid/hid_server.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/memory.h" #include "core/memory.h"
@ -154,7 +153,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r
{104, &IHidServer::DeactivateNpad, "DeactivateNpad"}, {104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
{106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"}, {106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
{107, &IHidServer::DisconnectNpad, "DisconnectNpad"}, {107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
{108, C<&IHidServer::GetPlayerLedPattern>, "GetPlayerLedPattern"}, {108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"},
{109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"}, {109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
{120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, {120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
{121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, {121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
@ -1137,39 +1136,19 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern, void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
Core::HID::NpadIdType npad_id) { 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);
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
switch (npad_id) { IPC::ResponseBuilder rb{ctx, 4};
case Core::HID::NpadIdType::Player1: rb.Push(result);
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 0}; rb.Push(pattern.raw);
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) { void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {

View File

@ -3,9 +3,7 @@
#pragma once #pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "hid_core/hid_types.h"
namespace Core { namespace Core {
class System; class System;
@ -68,8 +66,7 @@ private:
void DeactivateNpad(HLERequestContext& ctx); void DeactivateNpad(HLERequestContext& ctx);
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx); void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
void DisconnectNpad(HLERequestContext& ctx); void DisconnectNpad(HLERequestContext& ctx);
Result GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern, void GetPlayerLedPattern(HLERequestContext& ctx);
Core::HID::NpadIdType npad_id);
void ActivateNpadWithRevision(HLERequestContext& ctx); void ActivateNpadWithRevision(HLERequestContext& ctx);
void SetNpadJoyHoldType(HLERequestContext& ctx); void SetNpadJoyHoldType(HLERequestContext& ctx);
void GetNpadJoyHoldType(HLERequestContext& ctx); void GetNpadJoyHoldType(HLERequestContext& ctx);

View File

@ -111,8 +111,7 @@ private:
R_RETURN(result); R_RETURN(result);
} }
Result UpdateLatest(Out<CharInfo> out_char_info, const CharInfo& char_info, Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) {
SourceFlag source_flag) {
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag)); R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag));
@ -160,7 +159,7 @@ private:
R_RETURN(result); R_RETURN(result);
} }
Result UpdateLatest1(Out<StoreData> out_store_data, const StoreData& store_data, Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data,
SourceFlag source_flag) { SourceFlag source_flag) {
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
R_UNLESS(is_system, ResultPermissionDenied); R_UNLESS(is_system, ResultPermissionDenied);
@ -244,7 +243,7 @@ private:
R_SUCCEED(); R_SUCCEED();
} }
Result GetIndex(Out<s32> out_index, const CharInfo& char_info) { Result GetIndex(Out<s32> out_index, CharInfo& char_info) {
LOG_DEBUG(Service_Mii, "called"); LOG_DEBUG(Service_Mii, "called");
R_RETURN(manager->GetIndex(metadata, char_info, *out_index)); R_RETURN(manager->GetIndex(metadata, char_info, *out_index));
@ -258,25 +257,25 @@ private:
R_SUCCEED(); R_SUCCEED();
} }
Result Convert(Out<CharInfo> out_char_info, const Ver3StoreData& mii_v3) { Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) {
LOG_INFO(Service_Mii, "called"); LOG_INFO(Service_Mii, "called");
R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3)); R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3));
} }
Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, const CoreData& core_data) { Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) {
LOG_INFO(Service_Mii, "called"); LOG_INFO(Service_Mii, "called");
R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data)); R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data));
} }
Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, const CharInfo& char_info) { Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) {
LOG_INFO(Service_Mii, "called"); LOG_INFO(Service_Mii, "called");
R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info)); R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info));
} }
Result Append(const CharInfo& char_info) { Result Append(CharInfo& char_info) {
LOG_INFO(Service_Mii, "called"); LOG_INFO(Service_Mii, "called");
R_RETURN(manager->Append(metadata, char_info)); R_RETURN(manager->Append(metadata, char_info));

View File

@ -1405,7 +1405,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; 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::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{}; Service::PSC::Time::CalendarAdditionalInfo additional_info{};
@ -1416,7 +1416,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
amiibo_date.SetMonth(1); amiibo_date.SetMonth(1);
amiibo_date.SetDay(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) { ResultSuccess) {
amiibo_date.SetYear(calendar_time.year); amiibo_date.SetYear(calendar_time.year);
amiibo_date.SetMonth(calendar_time.month); amiibo_date.SetMonth(calendar_time.month);
@ -1431,10 +1431,10 @@ s64 NfcDevice::GetCurrentPosixTime() const {
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; 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{}; 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; return time_point.time_point;
} }

View File

@ -91,10 +91,10 @@ Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max
true); true);
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; 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{}; 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; const s64 elapsed_time = time_point.time_point - time_since_last_error;
if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) { 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); system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; 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{}; 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; time_since_last_error = time_point.time_point;
} }

View File

@ -83,9 +83,7 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
// Check if this memory block is heap. // Check if this memory block is heap.
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) { if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
if (region_start + region_size == svc_mem_info.base_address) { if (svc_mem_info.size > region_size) {
region_size += svc_mem_info.size;
} else if (svc_mem_info.size > region_size) {
region_size = svc_mem_info.size; region_size = svc_mem_info.size;
region_start = svc_mem_info.base_address; region_start = svc_mem_info.base_address;
} }

View File

@ -5,7 +5,6 @@
#include <array> #include <array>
#include <chrono> #include <chrono>
#include <fmt/format.h>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/intrusive_list.h" #include "common/intrusive_list.h"
@ -22,14 +21,8 @@ class System;
namespace Service::PSC::Time { namespace Service::PSC::Time {
using ClockSourceId = Common::UUID; using ClockSourceId = Common::UUID;
enum class TimeType : u8 {
UserSystemClock = 0,
NetworkSystemClock = 1,
LocalSystemClock = 2,
};
struct SteadyClockTimePoint { struct SteadyClockTimePoint {
constexpr bool IdMatches(const SteadyClockTimePoint& other) const { constexpr bool IdMatches(SteadyClockTimePoint& other) {
return clock_source_id == other.clock_source_id; return clock_source_id == other.clock_source_id;
} }
bool operator==(const SteadyClockTimePoint& other) const = default; bool operator==(const SteadyClockTimePoint& other) const = default;
@ -49,6 +42,12 @@ struct SystemClockContext {
static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!"); static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!");
static_assert(std::is_trivial_v<SystemClockContext>); static_assert(std::is_trivial_v<SystemClockContext>);
enum class TimeType : u8 {
UserSystemClock,
NetworkSystemClock,
LocalSystemClock,
};
struct CalendarTime { struct CalendarTime {
s16 year; s16 year;
s8 month; s8 month;
@ -68,10 +67,14 @@ struct CalendarAdditionalInfo {
}; };
static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!"); static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!");
using LocationName = std::array<char, 0x24>; struct LocationName {
std::array<char, 36> name;
};
static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!"); static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!");
using RuleVersion = std::array<char, 0x10>; struct RuleVersion {
std::array<char, 16> version;
};
static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!"); static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!");
struct ClockSnapshot { struct ClockSnapshot {
@ -149,8 +152,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) {
return std::chrono::nanoseconds(a + b); return std::chrono::nanoseconds(a + b);
} }
constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyClockTimePoint& a, constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTimePoint& a,
const SteadyClockTimePoint& b) { SteadyClockTimePoint& b) {
R_UNLESS(out_seconds, ResultInvalidArgument); R_UNLESS(out_seconds, ResultInvalidArgument);
R_UNLESS(a.IdMatches(b), ResultInvalidArgument); R_UNLESS(a.IdMatches(b), ResultInvalidArgument);
R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(), R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(),
@ -163,111 +166,3 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyC
} }
} // namespace Service::PSC::Time } // 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);
}
};

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // 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" #include "core/hle/service/psc/time/power_state_service.h"
namespace Service::PSC::Time { namespace Service::PSC::Time {
@ -12,34 +11,39 @@ IPowerStateRequestHandler::IPowerStateRequestHandler(
power_state_request_manager} { power_state_request_manager} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"}, {0, &IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle, "GetPowerStateRequestEventReadableHandle"},
{1, D<&IPowerStateRequestHandler::GetAndClearPowerStateRequest>, "GetAndClearPowerStateRequest"}, {1, &IPowerStateRequestHandler::GetAndClearPowerStateRequest, "GetAndClearPowerStateRequest"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
} }
Result IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle( void IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx) {
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called."); LOG_DEBUG(Service_Time, "called.");
*out_event = &m_power_state_request_manager.GetReadableEvent(); IPC::ResponseBuilder rb{ctx, 2, 1};
R_SUCCEED(); rb.Push(ResultSuccess);
rb.PushCopyObjects(m_power_state_request_manager.GetReadableEvent());
} }
Result IPowerStateRequestHandler::GetAndClearPowerStateRequest(Out<bool> out_cleared, void IPowerStateRequestHandler::GetAndClearPowerStateRequest(HLERequestContext& ctx) {
Out<u32> out_priority) {
LOG_DEBUG(Service_Time, "called."); LOG_DEBUG(Service_Time, "called.");
u32 priority{}; u32 priority{};
auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority); auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority);
*out_cleared = cleared;
if (cleared) { if (cleared) {
*out_priority = priority; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(priority);
rb.Push(cleared);
return;
} }
R_SUCCEED();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(cleared);
} }
} // namespace Service::PSC::Time } // namespace Service::PSC::Time

View File

@ -3,7 +3,6 @@
#pragma once #pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/power_state_request_manager.h" #include "core/hle/service/psc/time/power_state_request_manager.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
@ -22,10 +21,10 @@ public:
~IPowerStateRequestHandler() override = default; ~IPowerStateRequestHandler() override = default;
Result GetPowerStateRequestEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetAndClearPowerStateRequest(Out<bool> out_cleared, Out<u32> out_priority);
private: private:
void GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx);
void GetAndClearPowerStateRequest(HLERequestContext& ctx);
Core::System& m_system; Core::System& m_system;
PowerStateRequestManager& m_power_state_request_manager; PowerStateRequestManager& m_power_state_request_manager;
}; };

View File

@ -3,7 +3,6 @@
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.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/power_state_service.h"
#include "core/hle/service/psc/time/service_manager.h" #include "core/hle/service/psc/time/service_manager.h"
#include "core/hle/service/psc/time/static.h" #include "core/hle/service/psc/time/static.h"
@ -26,24 +25,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} { m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&ServiceManager::GetStaticServiceAsUser>, "GetStaticServiceAsUser"}, {0, &ServiceManager::Handle_GetStaticServiceAsUser, "GetStaticServiceAsUser"},
{5, D<&ServiceManager::GetStaticServiceAsAdmin>, "GetStaticServiceAsAdmin"}, {5, &ServiceManager::Handle_GetStaticServiceAsAdmin, "GetStaticServiceAsAdmin"},
{6, D<&ServiceManager::GetStaticServiceAsRepair>, "GetStaticServiceAsRepair"}, {6, &ServiceManager::Handle_GetStaticServiceAsRepair, "GetStaticServiceAsRepair"},
{9, D<&ServiceManager::GetStaticServiceAsServiceManager>, "GetStaticServiceAsServiceManager"}, {9, &ServiceManager::Handle_GetStaticServiceAsServiceManager, "GetStaticServiceAsServiceManager"},
{10, D<&ServiceManager::SetupStandardSteadyClockCore>, "SetupStandardSteadyClockCore"}, {10, &ServiceManager::Handle_SetupStandardSteadyClockCore, "SetupStandardSteadyClockCore"},
{11, D<&ServiceManager::SetupStandardLocalSystemClockCore>, "SetupStandardLocalSystemClockCore"}, {11, &ServiceManager::Handle_SetupStandardLocalSystemClockCore, "SetupStandardLocalSystemClockCore"},
{12, D<&ServiceManager::SetupStandardNetworkSystemClockCore>, "SetupStandardNetworkSystemClockCore"}, {12, &ServiceManager::Handle_SetupStandardNetworkSystemClockCore, "SetupStandardNetworkSystemClockCore"},
{13, D<&ServiceManager::SetupStandardUserSystemClockCore>, "SetupStandardUserSystemClockCore"}, {13, &ServiceManager::Handle_SetupStandardUserSystemClockCore, "SetupStandardUserSystemClockCore"},
{14, D<&ServiceManager::SetupTimeZoneServiceCore>, "SetupTimeZoneServiceCore"}, {14, &ServiceManager::Handle_SetupTimeZoneServiceCore, "SetupTimeZoneServiceCore"},
{15, D<&ServiceManager::SetupEphemeralNetworkSystemClockCore>, "SetupEphemeralNetworkSystemClockCore"}, {15, &ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore, "SetupEphemeralNetworkSystemClockCore"},
{50, D<&ServiceManager::GetStandardLocalClockOperationEvent>, "GetStandardLocalClockOperationEvent"}, {50, &ServiceManager::Handle_GetStandardLocalClockOperationEvent, "GetStandardLocalClockOperationEvent"},
{51, D<&ServiceManager::GetStandardNetworkClockOperationEventForServiceManager>, "GetStandardNetworkClockOperationEventForServiceManager"}, {51, &ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager, "GetStandardNetworkClockOperationEventForServiceManager"},
{52, D<&ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager>, "GetEphemeralNetworkClockOperationEventForServiceManager"}, {52, &ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager, "GetEphemeralNetworkClockOperationEventForServiceManager"},
{60, D<&ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"}, {60, &ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
{100, D<&ServiceManager::SetStandardSteadyClockBaseTime>, "SetStandardSteadyClockBaseTime"}, {100, &ServiceManager::Handle_SetStandardSteadyClockBaseTime, "SetStandardSteadyClockBaseTime"},
{200, D<&ServiceManager::GetClosestAlarmUpdatedEvent>, "GetClosestAlarmUpdatedEvent"}, {200, &ServiceManager::Handle_GetClosestAlarmUpdatedEvent, "GetClosestAlarmUpdatedEvent"},
{201, D<&ServiceManager::CheckAndSignalAlarms>, "CheckAndSignalAlarms"}, {201, &ServiceManager::Handle_CheckAndSignalAlarms, "CheckAndSignalAlarms"},
{202, D<&ServiceManager::GetClosestAlarmInfo>, "GetClosestAlarmInfo "}, {202, &ServiceManager::Handle_GetClosestAlarmInfo, "GetClosestAlarmInfo "},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
@ -53,39 +52,302 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
m_ephemeral_system_context_writer.Link(m_ephemeral_operation); m_ephemeral_system_context_writer.Link(m_ephemeral_operation);
} }
Result ServiceManager::GetStaticServiceAsUser(OutInterface<StaticService> out_service) { 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) {
LOG_DEBUG(Service_Time, "called."); 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")); R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u"));
} }
Result ServiceManager::GetStaticServiceAsAdmin(OutInterface<StaticService> out_service) { Result ServiceManager::GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a")); R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a"));
} }
Result ServiceManager::GetStaticServiceAsRepair(OutInterface<StaticService> out_service) { Result ServiceManager::GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r")); R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r"));
} }
Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service) { Result ServiceManager::GetStaticServiceAsServiceManager(
LOG_DEBUG(Service_Time, "called."); std::shared_ptr<StaticService>& out_service) {
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm")); R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm"));
} }
Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
Common::UUID& clock_source_id, s64 rtc_offset, s64 internal_offset, s64 test_offset,
s64 internal_offset, s64 test_offset) { bool is_rtc_reset_detected) {
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, m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset,
is_rtc_reset_detected); is_rtc_reset_detected);
auto time = m_steady_clock.GetRawTime(); auto time = m_steady_clock.GetRawTime();
@ -103,10 +365,6 @@ Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected,
} }
Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) { 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.SetContextWriter(m_local_system_context_writer);
m_local_system_clock.Initialize(context, time); m_local_system_clock.Initialize(context, time);
@ -116,12 +374,12 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con
Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context, Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context,
s64 accuracy) { 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 // 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. // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
m_local_system_clock.GetContext(context); // to avoid it being stuck at 0.
if (context == Service::PSC::Time::SystemClockContext{}) {
m_local_system_clock.GetContext(context);
}
m_network_system_clock.SetContextWriter(m_network_system_context_writer); m_network_system_clock.SetContextWriter(m_network_system_context_writer);
m_network_system_clock.Initialize(context, accuracy); m_network_system_clock.Initialize(context, accuracy);
@ -130,10 +388,14 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction, Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
SteadyClockTimePoint& time_point) { bool automatic_correction) {
LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}", // TODO this is a hack! The user clock should be updated independently, from the ntc service
automatic_correction, time_point, time_point.clock_source_id.RawString()); // 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);
}
m_user_system_clock.SetAutomaticCorrection(automatic_correction); m_user_system_clock.SetAutomaticCorrection(automatic_correction);
m_user_system_clock.SetTimePointAndSignal(time_point); m_user_system_clock.SetTimePointAndSignal(time_point);
@ -144,16 +406,10 @@ Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correctio
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
u32 location_count,
SteadyClockTimePoint& time_point, SteadyClockTimePoint& time_point,
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) { RuleVersion& rule_version, u32 location_count,
LOG_DEBUG(Service_Time, std::span<const u8> rule_buffer) {
"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) { if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) {
LOG_ERROR(Service_Time, "Failed to parse time zone binary!"); LOG_ERROR(Service_Time, "Failed to parse time zone binary!");
} }
@ -168,8 +424,6 @@ Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion&
} }
Result ServiceManager::SetupEphemeralNetworkSystemClockCore() { Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
LOG_DEBUG(Service_Time, "called.");
m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer); m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer);
m_ephemeral_network_clock.SetInitialized(); m_ephemeral_network_clock.SetInitialized();
@ -177,41 +431,30 @@ Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::GetStandardLocalClockOperationEvent( Result ServiceManager::GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event) {
OutCopyHandle<Kernel::KReadableEvent> out_event) { *out_event = m_local_operation.m_event;
LOG_DEBUG(Service_Time, "called.");
*out_event = &m_local_operation.m_event->GetReadableEvent();
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager( Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager(
OutCopyHandle<Kernel::KReadableEvent> out_event) { Kernel::KEvent** out_event) {
LOG_DEBUG(Service_Time, "called."); *out_event = m_network_operation.m_event;
*out_event = &m_network_operation.m_event->GetReadableEvent();
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager( Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager(
OutCopyHandle<Kernel::KReadableEvent> out_event) { Kernel::KEvent** out_event) {
LOG_DEBUG(Service_Time, "called."); *out_event = m_ephemeral_operation.m_event;
*out_event = &m_ephemeral_operation.m_event->GetReadableEvent();
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event) { Kernel::KEvent** out_event) {
LOG_DEBUG(Service_Time, "called."); *out_event = &m_user_system_clock.GetEvent();
*out_event = &m_user_system_clock.GetEvent().GetReadableEvent();
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) { Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
LOG_DEBUG(Service_Time, "called. base_time={}", base_time);
m_steady_clock.SetRtcOffset(base_time); m_steady_clock.SetRtcOffset(base_time);
auto time = m_steady_clock.GetRawTime(); auto time = m_steady_clock.GetRawTime();
auto ticks = m_system.CoreTiming().GetClockTicks(); auto ticks = m_system.CoreTiming().GetClockTicks();
@ -225,63 +468,26 @@ Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::GetClosestAlarmUpdatedEvent( Result ServiceManager::GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event) {
OutCopyHandle<Kernel::KReadableEvent> out_event) { *out_event = &m_alarms.GetEvent();
LOG_DEBUG(Service_Time, "called.");
*out_event = &m_alarms.GetEvent().GetReadableEvent();
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::CheckAndSignalAlarms() { Result ServiceManager::CheckAndSignalAlarms() {
LOG_DEBUG(Service_Time, "called.");
m_alarms.CheckAndSignal(); m_alarms.CheckAndSignal();
R_SUCCEED(); R_SUCCEED();
} }
Result ServiceManager::GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Result ServiceManager::GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time) {
Out<s64> out_time) {
Alarm* alarm{nullptr}; Alarm* alarm{nullptr};
*out_is_valid = m_alarms.GetClosestAlarm(&alarm); out_is_valid = m_alarms.GetClosestAlarm(&alarm);
if (*out_is_valid) { if (out_is_valid) {
*out_info = { out_info = {
.alert_time = alarm->GetAlertTime(), .alert_time = alarm->GetAlertTime(),
.priority = alarm->GetPriority(), .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(); R_SUCCEED();
} }

View File

@ -6,7 +6,6 @@
#include <list> #include <list>
#include <memory> #include <memory>
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h" #include "core/hle/service/psc/time/manager.h"
@ -30,38 +29,55 @@ public:
ServerManager* server_manager); ServerManager* server_manager);
~ServiceManager() override = default; ~ServiceManager() override = default;
Result GetStaticServiceAsUser(OutInterface<StaticService> out_service); Result GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service);
Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service); Result GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service);
Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service); Result GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service);
Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service); Result GetStaticServiceAsServiceManager(std::shared_ptr<StaticService>& out_service);
Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id, Result SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
s64 rtc_offset, s64 internal_offset, s64 test_offset); s64 internal_offset, s64 test_offset,
bool is_rtc_reset_detected);
Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time); Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time);
Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy); Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy);
Result SetupStandardUserSystemClockCore(bool automatic_correction, Result SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
SteadyClockTimePoint& time_point); bool automatic_correction);
Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, Result SetupTimeZoneServiceCore(LocationName& name, SteadyClockTimePoint& time_point,
u32 location_count, SteadyClockTimePoint& time_point, RuleVersion& rule_version, u32 location_count,
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer); std::span<const u8> rule_buffer);
Result SetupEphemeralNetworkSystemClockCore(); Result SetupEphemeralNetworkSystemClockCore();
Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event);
Result GetStandardNetworkClockOperationEventForServiceManager( Result GetStandardNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetEphemeralNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
Result GetEphemeralNetworkClockOperationEventForServiceManager( Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(Kernel::KEvent** out_event);
OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event);
Result SetStandardSteadyClockBaseTime(s64 base_time); Result SetStandardSteadyClockBaseTime(s64 base_time);
Result GetClosestAlarmUpdatedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event);
Result CheckAndSignalAlarms(); Result CheckAndSignalAlarms();
Result GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Out<s64> out_time); Result GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time);
private: private:
void CheckAndSetupServicesSAndP(); void CheckAndSetupServicesSAndP();
void SetupSAndP(); void SetupSAndP();
Result GetStaticService(OutInterface<StaticService> out_service, Result GetStaticService(std::shared_ptr<StaticService>& out_service,
StaticServiceSetupInfo setup_info, const char* name); 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; Core::System& m_system;
std::shared_ptr<TimeManager> m_time; std::shared_ptr<TimeManager> m_time;
ServerManager& m_server_manager; ServerManager& m_server_manager;

View File

@ -1,11 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_shared_memory.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/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_local_system_clock_core.h"
#include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h" #include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h"
@ -41,122 +39,358 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup
m_time->m_shared_memory} { m_time->m_shared_memory} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"}, {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"},
{1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"}, {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
{2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"}, {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"},
{3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"}, {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"},
{4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"}, {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
{5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"}, {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"},
{20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
{50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"}, {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"},
{51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"}, {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"},
{100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
{101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
{102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"}, {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"},
{200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"}, {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
{201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
{300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"}, {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
{400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"}, {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"},
{401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"}, {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
{500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"}, {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
{501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"}, {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
} }
Result StaticService::GetStandardUserSystemClock(OutInterface<SystemClock> out_service) { Result StaticService::GetClockSnapshotImpl(ClockSnapshot& out_snapshot,
LOG_DEBUG(Service_Time, "called."); SystemClockContext& user_context,
SystemClockContext& network_context, TimeType type) {
out_snapshot.user_context = user_context;
out_snapshot.network_context = network_context;
*out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock, R_TRY(
m_setup_info.can_write_user_clock, m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot.steady_clock_time_point));
m_setup_info.can_write_uninitialized_clock);
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(); R_SUCCEED();
} }
Result StaticService::GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service) { void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called."); LOG_DEBUG(Service_Time, "called.");
*out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock, std::shared_ptr<SystemClock> service{};
m_setup_info.can_write_network_clock, auto res = GetStandardUserSystemClock(service);
m_setup_info.can_write_uninitialized_clock);
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);
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetStandardSteadyClock(OutInterface<SteadyClock> out_service) { Result StaticService::GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) {
LOG_DEBUG(Service_Time, "called."); 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();
}
*out_service = Result StaticService::GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service) {
out_service =
std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock, std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock,
m_setup_info.can_write_uninitialized_clock); m_setup_info.can_write_uninitialized_clock);
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) { Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) {
LOG_DEBUG(Service_Time, "called."); out_service =
*out_service =
std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone, std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone,
m_setup_info.can_write_timezone_device_location); m_setup_info.can_write_timezone_device_location);
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetStandardLocalSystemClock(OutInterface<SystemClock> out_service) { Result StaticService::GetStandardLocalSystemClock(std::shared_ptr<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,
*out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock, m_setup_info.can_write_uninitialized_clock);
m_setup_info.can_write_local_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service) { Result StaticService::GetEphemeralNetworkSystemClock(std::shared_ptr<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,
*out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock, m_setup_info.can_write_uninitialized_clock);
m_setup_info.can_write_network_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetSharedMemoryNativeHandle( Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
LOG_DEBUG(Service_Time, "called.");
*out_shared_memory = &m_shared_memory.GetKSharedMemory(); *out_shared_memory = &m_shared_memory.GetKSharedMemory();
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled) {
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); 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(); R_SUCCEED();
} }
Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
bool automatic_correction) { 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(), R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied); R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied);
@ -173,35 +407,22 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!"); out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
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(); R_SUCCEED();
} }
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Out<SteadyClockTimePoint> out_time_point) { 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); 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(); R_SUCCEED();
} }
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
SystemClockContext& context) { 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); R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized);
SteadyClockTimePoint time_point{}; SteadyClockTimePoint time_point{};
@ -212,16 +433,12 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_ti
auto one_second_ns{ auto one_second_ns{
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()}; std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()};
auto ticks{m_system.CoreTiming().GetClockTicks()}; auto ticks{m_system.CoreTiming().GetClockTicks()};
auto current_time_ns{ConvertToTimeSpan(ticks).count()}; auto current_time{ConvertToTimeSpan(ticks).count()};
*out_time = ((context.offset + time_point.time_point) - (current_time_ns / one_second_ns)); out_time = ((context.offset + time_point.time_point) - (current_time / one_second_ns));
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) { Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type) {
SCOPE_EXIT(
{ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
SystemClockContext user_context{}; SystemClockContext user_context{};
R_TRY(m_user_system_clock.GetContext(user_context)); R_TRY(m_user_system_clock.GetContext(user_context));
@ -231,101 +448,53 @@ Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType t
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
} }
Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type, Result StaticService::GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
OutClockSnapshot out_snapshot,
SystemClockContext& user_context, SystemClockContext& user_context,
SystemClockContext& network_context) { SystemClockContext& network_context,
SCOPE_EXIT({ TimeType type) {
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)); R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
} }
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(s64& out_time,
InClockSnapshot a, ClockSnapshot& a,
InClockSnapshot b) { ClockSnapshot& b) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference);
});
auto diff_s = 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 || if (a.user_context == b.user_context ||
!a->user_context.steady_time_point.IdMatches(b->user_context.steady_time_point)) { !a.user_context.steady_time_point.IdMatches(b.user_context.steady_time_point)) {
*out_difference = 0; out_time = 0;
R_SUCCEED(); R_SUCCEED();
} }
if (!a->is_automatic_correction_enabled || !b->is_automatic_correction_enabled) { if (!a.is_automatic_correction_enabled || !b.is_automatic_correction_enabled) {
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
R_SUCCEED(); R_SUCCEED();
} }
if (a->network_context.steady_time_point.IdMatches(a->steady_clock_time_point) || 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)) { b.network_context.steady_time_point.IdMatches(b.steady_clock_time_point)) {
*out_difference = 0; out_time = 0;
R_SUCCEED(); R_SUCCEED();
} }
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
R_SUCCEED(); R_SUCCEED();
} }
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, Result StaticService::CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b) {
InClockSnapshot b) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
s64 time_s{}; s64 time_s{};
auto res = 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) { if (res != ResultSuccess) {
R_UNLESS(a->network_time != 0 && b->network_time != 0, ResultTimeNotFound); R_UNLESS(a.network_time != 0 && b.network_time != 0, ResultTimeNotFound);
time_s = b->network_time - a->network_time; 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(); std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count();
R_SUCCEED(); 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 } // namespace Service::PSC::Time

View File

@ -3,7 +3,6 @@
#pragma once #pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/common.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
@ -30,44 +29,58 @@ class EphemeralNetworkSystemClockCore;
class SharedMemory; class SharedMemory;
class StaticService final : public ServiceFramework<StaticService> { class StaticService final : public ServiceFramework<StaticService> {
using InClockSnapshot = InLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
using OutClockSnapshot = OutLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
public: public:
explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info, explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info,
std::shared_ptr<TimeManager> time, const char* name); std::shared_ptr<TimeManager> time, const char* name);
~StaticService() override = default; ~StaticService() override = default;
Result GetStandardUserSystemClock(OutInterface<SystemClock> out_service); Result GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service); Result GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetStandardSteadyClock(OutInterface<SteadyClock> out_service); Result GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service);
Result GetTimeZoneService(OutInterface<TimeZoneService> out_service); Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service);
Result GetStandardLocalSystemClock(OutInterface<SystemClock> out_service); Result GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service); Result GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory);
Result SetStandardSteadyClockInternalOffset(s64 offset_ns); Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled);
Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
Result GetStandardUserSystemClockInitialYear(Out<s32> out_year); Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient);
Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Out<SteadyClockTimePoint> out_time_point); SteadyClockTimePoint& out_time_point);
Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, Result CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, SystemClockContext& context);
SystemClockContext& context); Result GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type);
Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type); Result GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot,
SystemClockContext& user_context, SystemClockContext& user_context,
SystemClockContext& network_context); SystemClockContext& network_context,
Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, TimeType type);
InClockSnapshot a, InClockSnapshot b); Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, ClockSnapshot& a,
Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); ClockSnapshot& b);
Result CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b);
private: private:
Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context, Result GetClockSnapshotImpl(ClockSnapshot& out_snapshot, SystemClockContext& user_context,
SystemClockContext& network_context, TimeType type); 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; Core::System& m_system;
StaticServiceSetupInfo m_setup_info; StaticServiceSetupInfo m_setup_info;
std::shared_ptr<TimeManager> m_time; std::shared_ptr<TimeManager> m_time;

View File

@ -1,9 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/steady_clock.h" #include "core/hle/service/psc/time/steady_clock.h"
namespace Service::PSC::Time { namespace Service::PSC::Time {
@ -16,40 +14,114 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
can_write_uninitialized_clock} { can_write_uninitialized_clock} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"}, {0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"},
{2, D<&SteadyClock::GetTestOffset>, "GetTestOffset"}, {2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"},
{3, D<&SteadyClock::SetTestOffset>, "SetTestOffset"}, {3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"},
{100, D<&SteadyClock::GetRtcValue>, "GetRtcValue"}, {100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"},
{101, D<&SteadyClock::IsRtcResetDetected>, "IsRtcResetDetected"}, {101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"},
{102, D<&SteadyClock::GetSetupResultValue>, "GetSetupResultValue"}, {102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"},
{200, D<&SteadyClock::GetInternalOffset>, "GetInternalOffset"}, {200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
} }
Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) { void SteadyClock::Handle_GetCurrentTimePoint(HLERequestContext& ctx) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); LOG_DEBUG(Service_Time, "called.");
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), SteadyClockTimePoint time_point{};
ResultClockUninitialized); auto res = GetCurrentTimePoint(time_point);
R_RETURN(m_clock_core.GetCurrentTimePoint(*out_time_point)); IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<SteadyClockTimePoint>(time_point);
} }
Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) { void SteadyClock::Handle_GetTestOffset(HLERequestContext& ctx) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); }); 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(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
*out_test_offset = m_clock_core.GetTestOffset(); R_RETURN(m_clock_core.GetCurrentTimePoint(out_time_point));
}
Result SteadyClock::GetTestOffset(s64& out_test_offset) {
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
out_test_offset = m_clock_core.GetTestOffset();
R_SUCCEED(); R_SUCCEED();
} }
Result SteadyClock::SetTestOffset(s64 test_offset) { 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_steady_clock, ResultPermissionDenied);
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
@ -58,43 +130,34 @@ Result SteadyClock::SetTestOffset(s64 test_offset) {
R_SUCCEED(); R_SUCCEED();
} }
Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) { Result SteadyClock::GetRtcValue(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(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
R_RETURN(m_clock_core.GetRtcValue(*out_rtc_value)); R_RETURN(m_clock_core.GetRtcValue(out_rtc_value));
} }
Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) { Result SteadyClock::IsRtcResetDetected(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(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
*out_is_detected = m_clock_core.IsResetDetected(); out_is_detected = m_clock_core.IsResetDetected();
R_SUCCEED(); R_SUCCEED();
} }
Result SteadyClock::GetSetupResultValue(Out<Result> out_result) { Result SteadyClock::GetSetupResultValue(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(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
*out_result = m_clock_core.GetSetupResultValue(); out_result = m_clock_core.GetSetupResultValue();
R_SUCCEED(); R_SUCCEED();
} }
Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) { Result SteadyClock::GetInternalOffset(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(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
*out_internal_offset = m_clock_core.GetInternalOffset(); out_internal_offset = m_clock_core.GetInternalOffset();
R_SUCCEED(); R_SUCCEED();
} }

View File

@ -3,7 +3,6 @@
#pragma once #pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h" #include "core/hle/service/psc/time/manager.h"
@ -23,15 +22,23 @@ public:
~SteadyClock() override = default; ~SteadyClock() override = default;
Result GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point); Result GetCurrentTimePoint(SteadyClockTimePoint& out_time_point);
Result GetTestOffset(Out<s64> out_test_offset); Result GetTestOffset(s64& out_test_offset);
Result SetTestOffset(s64 test_offset); Result SetTestOffset(s64 test_offset);
Result GetRtcValue(Out<s64> out_rtc_value); Result GetRtcValue(s64& out_rtc_value);
Result IsRtcResetDetected(Out<bool> out_is_detected); Result IsRtcResetDetected(bool& out_is_detected);
Result GetSetupResultValue(Out<Result> out_result); Result GetSetupResultValue(Result& out_result);
Result GetInternalOffset(Out<s64> out_internal_offset); Result GetInternalOffset(s64& out_internal_offset);
private: 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; Core::System& m_system;
StandardSteadyClockCore& m_clock_core; StandardSteadyClockCore& m_clock_core;

View File

@ -1,9 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/system_clock.h" #include "core/hle/service/psc/time/system_clock.h"
namespace Service::PSC::Time { namespace Service::PSC::Time {
@ -15,28 +13,83 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo
can_write_uninitialized_clock} { can_write_uninitialized_clock} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"}, {0, &SystemClock::Handle_GetCurrentTime, "GetCurrentTime"},
{1, D<&SystemClock::SetCurrentTime>, "SetCurrentTime"}, {1, &SystemClock::Handle_SetCurrentTime, "SetCurrentTime"},
{2, D<&SystemClock::GetSystemClockContext>, "GetSystemClockContext"}, {2, &SystemClock::Handle_GetSystemClockContext, "GetSystemClockContext"},
{3, D<&SystemClock::SetSystemClockContext>, "SetSystemClockContext"}, {3, &SystemClock::Handle_SetSystemClockContext, "SetSystemClockContext"},
{4, D<&SystemClock::GetOperationEventReadableHandle>, "GetOperationEventReadableHandle"}, {4, &SystemClock::Handle_GetOperationEventReadableHandle, "GetOperationEventReadableHandle"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
} }
Result SystemClock::GetCurrentTime(Out<s64> out_time) { void SystemClock::Handle_GetCurrentTime(HLERequestContext& ctx) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); }); LOG_DEBUG(Service_Time, "called.");
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(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
R_RETURN(m_clock_core.GetCurrentTime(out_time.Get())); R_RETURN(m_clock_core.GetCurrentTime(&out_time));
} }
Result SystemClock::SetCurrentTime(s64 time) { Result SystemClock::SetCurrentTime(s64 time) {
LOG_DEBUG(Service_Time, "called. time={}", time);
R_UNLESS(m_can_write_clock, ResultPermissionDenied); R_UNLESS(m_can_write_clock, ResultPermissionDenied);
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
@ -44,18 +97,14 @@ Result SystemClock::SetCurrentTime(s64 time) {
R_RETURN(m_clock_core.SetCurrentTime(time)); R_RETURN(m_clock_core.SetCurrentTime(time));
} }
Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) { Result SystemClock::GetSystemClockContext(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(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
R_RETURN(m_clock_core.GetContext(*out_context)); R_RETURN(m_clock_core.GetContext(out_context));
} }
Result SystemClock::SetSystemClockContext(SystemClockContext& 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_clock, ResultPermissionDenied);
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized); ResultClockUninitialized);
@ -63,10 +112,7 @@ Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
R_RETURN(m_clock_core.SetContextAndWrite(context)); R_RETURN(m_clock_core.SetContextAndWrite(context));
} }
Result SystemClock::GetOperationEventReadableHandle( Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) {
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
if (!m_operation_event) { if (!m_operation_event) {
m_operation_event = std::make_unique<OperationEvent>(m_system); m_operation_event = std::make_unique<OperationEvent>(m_system);
R_UNLESS(m_operation_event != nullptr, ResultFailed); R_UNLESS(m_operation_event != nullptr, ResultFailed);
@ -74,7 +120,7 @@ Result SystemClock::GetOperationEventReadableHandle(
m_clock_core.LinkOperationEvent(*m_operation_event); m_clock_core.LinkOperationEvent(*m_operation_event);
} }
*out_event = &m_operation_event->m_event->GetReadableEvent(); *out_event = m_operation_event->m_event;
R_SUCCEED(); R_SUCCEED();
} }

View File

@ -3,7 +3,6 @@
#pragma once #pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h" #include "core/hle/service/psc/time/manager.h"
@ -23,13 +22,19 @@ public:
~SystemClock() override = default; ~SystemClock() override = default;
Result GetCurrentTime(Out<s64> out_time); Result GetCurrentTime(s64& out_time);
Result SetCurrentTime(s64 time); Result SetCurrentTime(s64 time);
Result GetSystemClockContext(Out<SystemClockContext> out_context); Result GetSystemClockContext(SystemClockContext& out_context);
Result SetSystemClockContext(SystemClockContext& context); Result SetSystemClockContext(SystemClockContext& context);
Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetOperationEventReadableHandle(Kernel::KEvent** out_event);
private: 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; Core::System& m_system;
SystemClockCore& m_clock_core; SystemClockCore& m_clock_core;

View File

@ -5,7 +5,7 @@
namespace Service::PSC::Time { namespace Service::PSC::Time {
namespace { namespace {
constexpr Result ValidateRule(const Tz::Rule& rule) { constexpr Result ValidateRule(Tz::Rule& rule) {
if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) || if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) ||
rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) || rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) ||
rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) { rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) {
@ -26,7 +26,7 @@ constexpr Result ValidateRule(const Tz::Rule& rule) {
R_SUCCEED(); R_SUCCEED();
} }
constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s32 index, constexpr bool GetTimeZoneTime(s64& out_time, Tz::Rule& rule, s64 time, s32 index,
s32 index_offset) { s32 index_offset) {
s32 found_idx{}; s32 found_idx{};
s32 expected_index{index + index_offset}; s32 expected_index{index + index_offset};
@ -107,7 +107,7 @@ Result TimeZone::GetTimePoint(SteadyClockTimePoint& out_time_point) {
Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time, Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time, CalendarAdditionalInfo& out_additional_info, s64 time,
const Tz::Rule& rule) { Tz::Rule& rule) {
std::scoped_lock l{m_mutex}; std::scoped_lock l{m_mutex};
R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule)); 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)); R_RETURN(ParseBinaryImpl(out_rule, binary));
} }
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
const CalendarTime& calendar, const Tz::Rule& rule) { CalendarTime& calendar, Tz::Rule& rule) {
std::scoped_lock l{m_mutex}; std::scoped_lock l{m_mutex};
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, rule, -1); auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1);
if (res != ResultSuccess) { if (res != ResultSuccess) {
if (res == ResultTimeZoneNotFound) { if (res == ResultTimeZoneNotFound) {
@ -157,11 +157,11 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, size_t ou
R_RETURN(res); R_RETURN(res);
} }
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
size_t out_times_max_count, const CalendarTime& calendar) { u32 out_times_count, CalendarTime& calendar) {
std::scoped_lock l{m_mutex}; std::scoped_lock l{m_mutex};
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, m_my_rule, -1); auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, m_my_rule, -1);
if (res != ResultSuccess) { if (res != ResultSuccess) {
if (res == ResultTimeZoneNotFound) { 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, Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time, CalendarAdditionalInfo& out_additional_info, s64 time,
const Tz::Rule& rule) { Tz::Rule& rule) {
R_TRY(ValidateRule(rule)); R_TRY(ValidateRule(rule));
Tz::CalendarTimeInternal calendar_internal{}; Tz::CalendarTimeInternal calendar_internal{};
@ -212,23 +212,20 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
R_SUCCEED(); R_SUCCEED();
} }
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
size_t out_times_max_count, const CalendarTime& calendar, CalendarTime& calendar, Tz::Rule& rule, s32 is_dst) {
const Tz::Rule& rule, s32 is_dst) {
R_TRY(ValidateRule(rule)); R_TRY(ValidateRule(rule));
CalendarTime local_calendar{calendar}; calendar.month -= 1;
calendar.year -= 1900;
local_calendar.month -= 1;
local_calendar.year -= 1900;
Tz::CalendarTimeInternal internal{ Tz::CalendarTimeInternal internal{
.tm_sec = local_calendar.second, .tm_sec = calendar.second,
.tm_min = local_calendar.minute, .tm_min = calendar.minute,
.tm_hour = local_calendar.hour, .tm_hour = calendar.hour,
.tm_mday = local_calendar.day, .tm_mday = calendar.day,
.tm_mon = local_calendar.month, .tm_mon = calendar.month,
.tm_year = local_calendar.year, .tm_year = calendar.year,
.tm_wday = 0, .tm_wday = 0,
.tm_yday = 0, .tm_yday = 0,
.tm_isdst = is_dst, .tm_isdst = is_dst,
@ -246,9 +243,9 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times,
R_RETURN(ResultTimeZoneNotFound); R_RETURN(ResultTimeZoneNotFound);
} }
if (internal.tm_sec != local_calendar.second || internal.tm_min != local_calendar.minute || if (internal.tm_sec != calendar.second || internal.tm_min != calendar.minute ||
internal.tm_hour != local_calendar.hour || internal.tm_mday != local_calendar.day || internal.tm_hour != calendar.hour || internal.tm_mday != calendar.day ||
internal.tm_mon != local_calendar.month || internal.tm_year != local_calendar.year) { internal.tm_mon != calendar.month || internal.tm_year != calendar.year) {
R_RETURN(ResultTimeZoneNotFound); R_RETURN(ResultTimeZoneNotFound);
} }
@ -257,7 +254,7 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times,
} }
out_times[0] = time; out_times[0] = time;
if (out_times_max_count < 2) { if (out_times_count < 2) {
out_count = 1; out_count = 1;
R_SUCCEED(); R_SUCCEED();
} }

View File

@ -32,24 +32,23 @@ public:
Result GetTimePoint(SteadyClockTimePoint& out_time_point); Result GetTimePoint(SteadyClockTimePoint& out_time_point);
Result ToCalendarTime(CalendarTime& out_calendar_time, Result ToCalendarTime(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time, CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
const Tz::Rule& rule);
Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time, Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time,
CalendarAdditionalInfo& calendar_additional, s64 time); CalendarAdditionalInfo& calendar_additional, s64 time);
Result ParseBinary(LocationName& name, std::span<const u8> binary); Result ParseBinary(LocationName& name, std::span<const u8> binary);
Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
Result ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
const CalendarTime& calendar, const Tz::Rule& rule); CalendarTime& calendar, Tz::Rule& rule);
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
size_t out_times_max_count, const CalendarTime& calendar); CalendarTime& calendar);
private: private:
Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary); Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
Result ToCalendarTimeImpl(CalendarTime& out_calendar_time, Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time, CalendarAdditionalInfo& out_additional_info, s64 time,
const Tz::Rule& rule); Tz::Rule& rule);
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, Result ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
const CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst); CalendarTime& calendar, Tz::Rule& rule, s32 is_dst);
bool m_initialized{}; bool m_initialized{};
std::recursive_mutex m_mutex; std::recursive_mutex m_mutex;

View File

@ -2,10 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <tz/tz.h> #include <tz/tz.h>
#include "common/scope_exit.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/time_zone_service.h" #include "core/hle/service/psc/time/time_zone_service.h"
namespace Service::PSC::Time { namespace Service::PSC::Time {
@ -17,78 +14,240 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore&
can_write_timezone_device_location} { can_write_timezone_device_location} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"}, {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"},
{1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"}, {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"},
{2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"}, {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"},
{3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"}, {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"},
{4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"}, {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"},
{5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"}, {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
{6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"}, {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"},
{7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"}, {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"},
{8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"}, {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"},
{20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"}, {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"},
{100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"}, {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"},
{101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"}, {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
{201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"}, {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"},
{202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"}, {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
} }
Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) { void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_time_zone.GetLocationName(*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);
} }
Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) { void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!"); LOG_DEBUG(Service_Time, "called.");
R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); IPC::RequestParser rp{ctx};
R_RETURN(ResultNotImplemented); [[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);
} }
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_time_zone.GetTotalLocationCount(*out_count)); u32 count{};
auto res = GetTotalLocationNameCount(count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
} }
Result TimeZoneService::LoadLocationNameList( void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { LOG_DEBUG(Service_Time, "called.");
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
R_RETURN(ResultNotImplemented); IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
} }
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) { void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!"); LOG_DEBUG(Service_Time, "called.");
R_RETURN(ResultNotImplemented); IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
} }
Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) { void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_time_zone.GetRuleVersion(*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);
} }
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) {
Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) { LOG_DEBUG(Service_Time, "called.");
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}",
*out_location_name, *out_time_point);
});
R_TRY(m_time_zone.GetLocationName(*out_location_name)); LocationName name{};
R_RETURN(m_time_zone.GetTimePoint(*out_time_point)); 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);
} }
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule( void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) {
LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { LOG_DEBUG(Service_Time, "called.");
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_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
R_TRY(m_time_zone.ParseBinary(location_name, binary)); R_TRY(m_time_zone.ParseBinary(location_name, binary));
@ -99,67 +258,32 @@ Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
R_SUCCEED(); R_SUCCEED();
} }
Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule, Result TimeZoneService::ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary) {
InBuffer<BufferAttr_HipcAutoSelect> binary) { R_RETURN(m_time_zone.ParseBinaryInto(out_rule, binary));
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_time_zone.ParseBinaryInto(*out_rule, binary));
} }
Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( Result TimeZoneService::ToCalendarTime(CalendarTime& out_calendar_time,
OutCopyHandle<Kernel::KReadableEvent> out_event) { CalendarAdditionalInfo& out_additional_info, s64 time,
LOG_DEBUG(Service_Time, "called. This function is not implemented!"); Tz::Rule& rule) {
R_RETURN(m_time_zone.ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
R_RETURN(ResultNotImplemented);
} }
Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time, Result TimeZoneService::ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info, s64 time, CalendarAdditionalInfo& out_additional_info,
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_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) { s64 time) {
SCOPE_EXIT({ R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
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, Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times,
OutArray<s64, BufferAttr_HipcPointer> out_times, u32 out_times_count, CalendarTime& calendar_time,
const CalendarTime& calendar_time, InRule rule) { Tz::Rule& rule) {
SCOPE_EXIT({ R_RETURN(m_time_zone.ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
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, Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
OutArray<s64, BufferAttr_HipcPointer> out_times, u32 out_times_count, CalendarTime& calendar_time) {
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( R_RETURN(
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time)); m_time_zone.ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time));
} }
} // namespace Service::PSC::Time } // namespace Service::PSC::Time

View File

@ -3,7 +3,6 @@
#pragma once #pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h" #include "core/hle/service/psc/time/manager.h"
@ -21,41 +20,45 @@ struct Rule;
namespace Service::PSC::Time { namespace Service::PSC::Time {
class TimeZoneService final : public ServiceFramework<TimeZoneService> { class TimeZoneService final : public ServiceFramework<TimeZoneService> {
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
public: public:
explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core, explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core,
TimeZone& time_zone, bool can_write_timezone_device_location); TimeZone& time_zone, bool can_write_timezone_device_location);
~TimeZoneService() override = default; ~TimeZoneService() override = default;
Result GetDeviceLocationName(Out<LocationName> out_location_name); Result GetDeviceLocationName(LocationName& out_location_name);
Result SetDeviceLocationName(LocationName& location_name); Result GetTotalLocationNameCount(u32& out_count);
Result GetTotalLocationNameCount(Out<u32> out_count); Result GetTimeZoneRuleVersion(RuleVersion& out_rule_version);
Result LoadLocationNameList(Out<u32> out_count, Result GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, LocationName& location_name);
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, Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
InBuffer<BufferAttr_HipcAutoSelect> binary); std::span<const u8> binary);
Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); Result ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary);
Result GetDeviceLocationNameOperationEventReadableHandle( Result ToCalendarTime(CalendarTime& out_calendar_time,
OutCopyHandle<Kernel::KReadableEvent> out_event); CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
Result ToCalendarTime(Out<CalendarTime> out_calendar_time, Result ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule); CalendarAdditionalInfo& out_additional_info, s64 time);
Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
Out<CalendarAdditionalInfo> out_additional_info, s64 time); CalendarTime& calendar_time, Tz::Rule& rule);
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
const CalendarTime& calendar_time, InRule rule); CalendarTime& calendar_time);
Result ToPosixTimeWithMyRule(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
const CalendarTime& calendar_time);
private: 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; Core::System& m_system;
StandardSteadyClockCore& m_clock_core; StandardSteadyClockCore& m_clock_core;

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/hle/service/set/setting_formats/system_settings.h" #include "core/hle/service/set/setting_formats/system_settings.h"
namespace Service::Set { namespace Service::Set {
@ -45,7 +44,7 @@ SystemSettings DefaultSystemSettings() {
.console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour,
}; };
settings.device_time_zone_location_name = Service::PSC::Time::LocationName{"UTC"}; settings.device_time_zone_location_name = {"UTC"};
settings.user_system_clock_automatic_correction_enabled = true; settings.user_system_clock_automatic_correction_enabled = true;
settings.primary_album_storage = PrimaryAlbumStorage::SdCard; settings.primary_album_storage = PrimaryAlbumStorage::SdCard;
@ -53,17 +52,6 @@ SystemSettings DefaultSystemSettings() {
settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0; settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0;
settings.vibration_master_volume = 1.0f; 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; return settings;
} }

View File

@ -213,9 +213,10 @@ struct SystemSettings {
// nn::settings::system::AudioVolume // nn::settings::system::AudioVolume
std::array<u8, 0x8> audio_volume_type0; std::array<u8, 0x8> audio_volume_type0;
std::array<u8, 0x8> audio_volume_type1; std::array<u8, 0x8> audio_volume_type1;
AudioOutputMode audio_output_mode_hdmi; // nn::settings::system::AudioOutputMode
AudioOutputMode audio_output_mode_speaker; s32 audio_output_mode_type0;
AudioOutputMode audio_output_mode_headphone; s32 audio_output_mode_type1;
s32 audio_output_mode_type2;
bool force_mute_on_headphone_removed; bool force_mute_on_headphone_removed;
INSERT_PADDING_BYTES(0x3); INSERT_PADDING_BYTES(0x3);
s32 headphone_volume_warning_count; s32 headphone_volume_warning_count;
@ -223,8 +224,9 @@ struct SystemSettings {
INSERT_PADDING_BYTES(0x3); INSERT_PADDING_BYTES(0x3);
// nn::settings::system::AudioVolume // nn::settings::system::AudioVolume
std::array<u8, 0x8> audio_volume_type2; std::array<u8, 0x8> audio_volume_type2;
AudioOutputMode audio_output_mode_type3; // nn::settings::system::AudioOutputMode
AudioOutputMode audio_output_mode_type4; s32 audio_output_mode_type3;
s32 audio_output_mode_type4;
bool hearing_protection_safeguard_flag; bool hearing_protection_safeguard_flag;
INSERT_PADDING_BYTES(0x3); INSERT_PADDING_BYTES(0x3);
INSERT_PADDING_BYTES(0x4); // Reserved INSERT_PADDING_BYTES(0x4); // Reserved

View File

@ -23,12 +23,9 @@ enum class AudioOutputMode : u32 {
/// This is nn::settings::system::AudioOutputModeTarget /// This is nn::settings::system::AudioOutputModeTarget
enum class AudioOutputModeTarget : u32 { enum class AudioOutputModeTarget : u32 {
None,
Hdmi, Hdmi,
Speaker, Speaker,
Headphone, Headphone,
Type3,
Type4,
}; };
/// This is nn::settings::system::AudioVolumeTarget /// This is nn::settings::system::AudioVolumeTarget
@ -370,12 +367,6 @@ struct AccountNotificationSettings {
static_assert(sizeof(AccountNotificationSettings) == 0x18, static_assert(sizeof(AccountNotificationSettings) == 0x18,
"AccountNotificationSettings is an invalid size"); "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 /// This is nn::settings::system::EulaVersion
struct EulaVersion { struct EulaVersion {
u32 version; u32 version;
@ -445,12 +436,6 @@ struct NotificationSettings {
}; };
static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); 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 /// This is nn::settings::system::SleepSettings
struct SleepSettings { struct SleepSettings {
SleepFlag flags; SleepFlag flags;

View File

@ -25,7 +25,7 @@
namespace Service::Set { namespace Service::Set {
namespace { namespace {
constexpr u32 SETTINGS_VERSION{3u}; constexpr u32 SETTINGS_VERSION{1u};
constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
struct SettingsHeader { struct SettingsHeader {
u64 magic; u64 magic;
@ -131,10 +131,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"}, {40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"},
{41, nullptr, "GetEdid"}, {41, nullptr, "GetEdid"},
{42, nullptr, "SetEdid"}, {42, nullptr, "SetEdid"},
{43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"}, {43, nullptr, "GetAudioOutputMode"},
{44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"}, {44, nullptr, "SetAudioOutputMode"},
{45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"}, {45, &ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved, "IsForceMuteOnHeadphoneRemoved"},
{46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"}, {46, &ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved, "SetForceMuteOnHeadphoneRemoved"},
{47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"}, {47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"},
{48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"}, {48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"},
{49, nullptr, "GetDataDeletionSettings"}, {49, nullptr, "GetDataDeletionSettings"},
@ -155,8 +155,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"}, {64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"},
{65, nullptr, "GetUsb30EnableFlag"}, {65, nullptr, "GetUsb30EnableFlag"},
{66, nullptr, "SetUsb30EnableFlag"}, {66, nullptr, "SetUsb30EnableFlag"},
{67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"}, {67, nullptr, "GetBatteryLot"},
{68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"}, {68, nullptr, "GetSerialNumber"},
{69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"}, {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"},
{70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"}, {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"},
{71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"}, {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"},
@ -184,11 +184,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, {93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
{94, nullptr, "GetFatalDirtyFlags"}, {94, nullptr, "GetFatalDirtyFlags"},
{95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"}, {95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
{96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"}, {96, nullptr, "SetAutoUpdateEnableFlag"},
{97, nullptr, "GetNxControllerSettings"}, {97, nullptr, "GetNxControllerSettings"},
{98, nullptr, "SetNxControllerSettings"}, {98, nullptr, "SetNxControllerSettings"},
{99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"}, {99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
{100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"}, {100, nullptr, "SetBatteryPercentageFlag"},
{101, nullptr, "GetExternalRtcResetFlag"}, {101, nullptr, "GetExternalRtcResetFlag"},
{102, nullptr, "SetExternalRtcResetFlag"}, {102, nullptr, "SetExternalRtcResetFlag"},
{103, nullptr, "GetUsbFullKeyEnableFlag"}, {103, nullptr, "GetUsbFullKeyEnableFlag"},
@ -208,12 +208,12 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{117, nullptr, "GetHeadphoneVolumeUpdateFlag"}, {117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
{118, nullptr, "SetHeadphoneVolumeUpdateFlag"}, {118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
{119, nullptr, "NeedsToUpdateHeadphoneVolume"}, {119, nullptr, "NeedsToUpdateHeadphoneVolume"},
{120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"}, {120, nullptr, "GetPushNotificationActivityModeOnSleep"},
{121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"}, {121, nullptr, "SetPushNotificationActivityModeOnSleep"},
{122, nullptr, "GetServiceDiscoveryControlSettings"}, {122, nullptr, "GetServiceDiscoveryControlSettings"},
{123, nullptr, "SetServiceDiscoveryControlSettings"}, {123, nullptr, "SetServiceDiscoveryControlSettings"},
{124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"}, {124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
{125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"}, {125, nullptr, "SetErrorReportSharePermission"},
{126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"}, {126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
{127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"}, {127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
@ -225,7 +225,7 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
{136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"}, {136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"},
{137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"}, {137, nullptr, "SetKeyboardLayout"},
{138, nullptr, "GetWebInspectorFlag"}, {138, nullptr, "GetWebInspectorFlag"},
{139, nullptr, "GetAllowedSslHosts"}, {139, nullptr, "GetAllowedSslHosts"},
{140, nullptr, "GetHostFsMountPoint"}, {140, nullptr, "GetHostFsMountPoint"},
@ -291,8 +291,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{200, nullptr, "SetButtonConfigRegisteredSettings"}, {200, nullptr, "SetButtonConfigRegisteredSettings"},
{201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"}, {201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"},
{202, nullptr, "SetFieldTestingFlag"}, {202, nullptr, "SetFieldTestingFlag"},
{203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"}, {203, nullptr, "GetPanelCrcMode"},
{204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"}, {204, nullptr, "SetPanelCrcMode"},
{205, nullptr, "GetNxControllerSettingsEx"}, {205, nullptr, "GetNxControllerSettingsEx"},
{206, nullptr, "SetNxControllerSettingsEx"}, {206, nullptr, "SetNxControllerSettingsEx"},
{207, nullptr, "GetHearingProtectionSafeguardFlag"}, {207, nullptr, "GetHearingProtectionSafeguardFlag"},
@ -349,7 +349,7 @@ bool ISystemSettingsServer::LoadSettingsFile(std::filesystem::path& path, auto&&
} }
SettingsHeader hdr{}; SettingsHeader hdr{};
file.read(reinterpret_cast<char*>(&hdr), sizeof(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) { if (!exists || !file_size_ok) {
@ -390,7 +390,7 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto&
} }
auto settings_base = path / "settings"; auto settings_base = path / "settings";
std::filesystem::path settings_tmp_file = settings_base; auto settings_tmp_file = settings_base;
settings_tmp_file = settings_tmp_file.replace_extension("tmp"); settings_tmp_file = settings_tmp_file.replace_extension("tmp");
std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out); std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out);
if (!file.is_open()) { if (!file.is_open()) {
@ -817,34 +817,7 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) { void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(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={}", LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
m_system_settings.force_mute_on_headphone_removed); m_system_settings.force_mute_on_headphone_removed);
@ -853,7 +826,7 @@ void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
rb.PushRaw(m_system_settings.force_mute_on_headphone_removed); rb.PushRaw(m_system_settings.force_mute_on_headphone_removed);
} }
void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) { void ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>(); m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>();
SetSaveNeeded(); SetSaveNeeded();
@ -996,26 +969,6 @@ void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) {
rb.Push(ResultSuccess); 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) { void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag); LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
@ -1179,17 +1132,6 @@ void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.auto_update_enable_flag); 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) { void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}", LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}",
m_system_settings.battery_percentage_flag); m_system_settings.battery_percentage_flag);
@ -1199,18 +1141,6 @@ void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.battery_percentage_flag); 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) { void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called."); LOG_DEBUG(Service_SET, "called.");
@ -1234,27 +1164,6 @@ void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestConte
rb.Push(offset); 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) { void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, error_report_share_permission={}", LOG_INFO(Service_SET, "called, error_report_share_permission={}",
m_system_settings.error_report_share_permission); m_system_settings.error_report_share_permission);
@ -1264,18 +1173,6 @@ void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx
rb.PushEnum(m_system_settings.error_report_share_permission); 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) { void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag); LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
@ -1296,22 +1193,22 @@ void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) {
} }
void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) { void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout); 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);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(m_system_settings.keyboard_layout)); rb.Push(static_cast<u32>(selected_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) { void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
@ -1403,25 +1300,6 @@ void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.field_testing_flag); 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() { void ISystemSettingsServer::SetupSettings() {
auto system_dir = auto system_dir =
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050"; Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050";
@ -1512,66 +1390,6 @@ Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) {
R_SUCCEED(); 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 { Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const {
out_id = m_private_settings.external_clock_source_id; out_id = m_private_settings.external_clock_source_id;
R_SUCCEED(); R_SUCCEED();

View File

@ -50,10 +50,6 @@ public:
Result GetVibrationMasterVolume(f32& out_volume) const; Result GetVibrationMasterVolume(f32& out_volume) const;
Result SetVibrationMasterVolume(f32 volume); 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 GetExternalSteadyClockSourceId(Common::UUID& out_id) const;
Result SetExternalSteadyClockSourceId(const Common::UUID& id); Result SetExternalSteadyClockSourceId(const Common::UUID& id);
Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const; Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
@ -101,10 +97,8 @@ private:
void GetSettingsItemValue(HLERequestContext& ctx); void GetSettingsItemValue(HLERequestContext& ctx);
void GetTvSettings(HLERequestContext& ctx); void GetTvSettings(HLERequestContext& ctx);
void SetTvSettings(HLERequestContext& ctx); void SetTvSettings(HLERequestContext& ctx);
void GetAudioOutputMode(HLERequestContext& ctx); void IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
void SetAudioOutputMode(HLERequestContext& ctx); void SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
void GetSpeakerAutoMuteFlag(HLERequestContext& ctx);
void SetSpeakerAutoMuteFlag(HLERequestContext& ctx);
void GetDebugModeFlag(HLERequestContext& ctx); void GetDebugModeFlag(HLERequestContext& ctx);
void GetQuestFlag(HLERequestContext& ctx); void GetQuestFlag(HLERequestContext& ctx);
void SetQuestFlag(HLERequestContext& ctx); void SetQuestFlag(HLERequestContext& ctx);
@ -117,8 +111,6 @@ private:
void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
void GetPrimaryAlbumStorage(HLERequestContext& ctx); void GetPrimaryAlbumStorage(HLERequestContext& ctx);
void SetPrimaryAlbumStorage(HLERequestContext& ctx); void SetPrimaryAlbumStorage(HLERequestContext& ctx);
void GetBatteryLot(HLERequestContext& ctx);
void GetSerialNumber(HLERequestContext& ctx);
void GetNfcEnableFlag(HLERequestContext& ctx); void GetNfcEnableFlag(HLERequestContext& ctx);
void SetNfcEnableFlag(HLERequestContext& ctx); void SetNfcEnableFlag(HLERequestContext& ctx);
void GetSleepSettings(HLERequestContext& ctx); void GetSleepSettings(HLERequestContext& ctx);
@ -134,19 +126,13 @@ private:
void SetBluetoothEnableFlag(HLERequestContext& ctx); void SetBluetoothEnableFlag(HLERequestContext& ctx);
void GetMiiAuthorId(HLERequestContext& ctx); void GetMiiAuthorId(HLERequestContext& ctx);
void GetAutoUpdateEnableFlag(HLERequestContext& ctx); void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
void SetAutoUpdateEnableFlag(HLERequestContext& ctx);
void GetBatteryPercentageFlag(HLERequestContext& ctx); void GetBatteryPercentageFlag(HLERequestContext& ctx);
void SetBatteryPercentageFlag(HLERequestContext& ctx);
void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx); void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx); void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
void GetErrorReportSharePermission(HLERequestContext& ctx); void GetErrorReportSharePermission(HLERequestContext& ctx);
void SetErrorReportSharePermission(HLERequestContext& ctx);
void GetAppletLaunchFlags(HLERequestContext& ctx); void GetAppletLaunchFlags(HLERequestContext& ctx);
void SetAppletLaunchFlags(HLERequestContext& ctx); void SetAppletLaunchFlags(HLERequestContext& ctx);
void GetKeyboardLayout(HLERequestContext& ctx); void GetKeyboardLayout(HLERequestContext& ctx);
void SetKeyboardLayout(HLERequestContext& ctx);
void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
@ -155,8 +141,6 @@ private:
void GetHomeMenuScheme(HLERequestContext& ctx); void GetHomeMenuScheme(HLERequestContext& ctx);
void GetHomeMenuSchemeModel(HLERequestContext& ctx); void GetHomeMenuSchemeModel(HLERequestContext& ctx);
void GetFieldTestingFlag(HLERequestContext& ctx); void GetFieldTestingFlag(HLERequestContext& ctx);
void GetPanelCrcMode(HLERequestContext& ctx);
void SetPanelCrcMode(HLERequestContext& ctx);
bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func); bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func);
bool StoreSettingsFile(std::filesystem::path& path, auto& settings); bool StoreSettingsFile(std::filesystem::path& path, auto& settings);

View File

@ -24,7 +24,6 @@ enum class Errno : u32 {
CONNRESET = 104, CONNRESET = 104,
NOTCONN = 107, NOTCONN = 107,
TIMEDOUT = 110, TIMEDOUT = 110,
CONNREFUSED = 111,
INPROGRESS = 115, INPROGRESS = 115,
}; };

View File

@ -25,8 +25,6 @@ Errno Translate(Network::Errno value) {
return Errno::MFILE; return Errno::MFILE;
case Network::Errno::PIPE: case Network::Errno::PIPE:
return Errno::PIPE; return Errno::PIPE;
case Network::Errno::CONNREFUSED:
return Errno::CONNREFUSED;
case Network::Errno::NOTCONN: case Network::Errno::NOTCONN:
return Errno::NOTCONN; return Errno::NOTCONN;
case Network::Errno::TIMEDOUT: case Network::Errno::TIMEDOUT:

View File

@ -693,23 +693,20 @@ std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() {
sockaddr_in addr; sockaddr_in addr;
socklen_t addrlen = sizeof(addr); socklen_t addrlen = sizeof(addr);
const bool wait_for_accept = !is_non_blocking; std::vector<WSAPOLLFD> host_pollfds{
if (wait_for_accept) { WSAPOLLFD{fd, POLLIN, 0},
std::vector<WSAPOLLFD> host_pollfds{ WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
WSAPOLLFD{fd, POLLIN, 0}, };
WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
};
while (true) { while (true) {
const int pollres = const int pollres =
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1); WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
if (host_pollfds[1].revents != 0) { if (host_pollfds[1].revents != 0) {
// Interrupt signaled before a client could be accepted, break // Interrupt signaled before a client could be accepted, break
return {AcceptResult{}, Errno::AGAIN}; return {AcceptResult{}, Errno::AGAIN};
} }
if (pollres > 0) { if (pollres > 0) {
break; break;
}
} }
} }
@ -916,7 +913,6 @@ Errno Socket::SetRcvTimeo(u32 value) {
Errno Socket::SetNonBlock(bool enable) { Errno Socket::SetNonBlock(bool enable) {
if (EnableNonBlock(fd, enable)) { if (EnableNonBlock(fd, enable)) {
is_non_blocking = enable;
return Errno::SUCCESS; return Errno::SUCCESS;
} }
return GetAndLogLastError(); return GetAndLogLastError();

View File

@ -166,9 +166,6 @@ public:
bool IsOpened() const override; bool IsOpened() const override;
void HandleProxyPacket(const ProxyPacket& packet) override; void HandleProxyPacket(const ProxyPacket& packet) override;
private:
bool is_non_blocking = false;
}; };
std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout);

View File

@ -781,7 +781,8 @@ struct Memory::Impl {
}, },
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); }); [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); });
if (ptr) { if (ptr) {
return Common::AtomicCompareAndSwap(reinterpret_cast<T*>(ptr), data, expected); const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr);
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
} }
return true; return true;
} }
@ -795,7 +796,8 @@ struct Memory::Impl {
}, },
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); }); [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); });
if (ptr) { if (ptr) {
return Common::AtomicCompareAndSwap(reinterpret_cast<u64*>(ptr), data, expected); const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr);
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
} }
return true; return true;
} }
@ -1091,6 +1093,20 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
[&] { rasterizer = true; }); [&] { rasterizer = true; });
if (rasterizer) { if (rasterizer) {
impl->InvalidateGPUMemory(ptr, size); impl->InvalidateGPUMemory(ptr, size);
const auto type = impl->current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Type();
if (type == Common::PageType::RasterizerCachedMemory) {
// Check if device mapped. If not, this bugged and we can unmark.
DAddr addr{};
Common::ScratchBuffer<u32> buffer;
impl->gpu_device_memory->ApplyOpOnPointer(ptr, buffer,
[&](DAddr address) { addr = address; });
if (addr == 0) {
LOG_ERROR(HW_Memory, "Fixing unmapped cached region {:#x}", GetInteger(vaddr));
impl->RasterizerMarkRegionCached(GetInteger(vaddr), size, false);
}
}
} }
#ifdef __linux__ #ifdef __linux__

View File

@ -7,6 +7,8 @@ add_executable(yuzu-room
yuzu_room.rc yuzu_room.rc
) )
create_target_directory_groups(yuzu-room)
target_link_libraries(yuzu-room PRIVATE common network) target_link_libraries(yuzu-room PRIVATE common network)
if (ENABLE_WEB_SERVICE) if (ENABLE_WEB_SERVICE)
target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE)
@ -26,5 +28,3 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS) if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h) target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h)
endif() endif()
create_target_directory_groups(yuzu-room)

View File

@ -298,16 +298,6 @@ void Config::ReadDebuggingValues() {
EndGroup(); EndGroup();
} }
#ifdef __unix__
void Config::ReadLinuxValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
ReadCategory(Settings::Category::Linux);
EndGroup();
}
#endif
void Config::ReadServiceValues() { void Config::ReadServiceValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Services)); BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
@ -414,9 +404,6 @@ void Config::ReadValues() {
ReadControlValues(); ReadControlValues();
ReadCoreValues(); ReadCoreValues();
ReadCpuValues(); ReadCpuValues();
#ifdef __unix__
ReadLinuxValues();
#endif
ReadRendererValues(); ReadRendererValues();
ReadAudioValues(); ReadAudioValues();
ReadSystemValues(); ReadSystemValues();
@ -517,9 +504,6 @@ void Config::SaveValues() {
SaveControlValues(); SaveControlValues();
SaveCoreValues(); SaveCoreValues();
SaveCpuValues(); SaveCpuValues();
#ifdef __unix__
SaveLinuxValues();
#endif
SaveRendererValues(); SaveRendererValues();
SaveAudioValues(); SaveAudioValues();
SaveSystemValues(); SaveSystemValues();
@ -594,16 +578,6 @@ void Config::SaveDebuggingValues() {
EndGroup(); EndGroup();
} }
#ifdef __unix__
void Config::SaveLinuxValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
WriteCategory(Settings::Category::Linux);
EndGroup();
}
#endif
void Config::SaveNetworkValues() { void Config::SaveNetworkValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Services)); BeginGroup(Settings::TranslateCategory(Settings::Category::Services));

View File

@ -76,9 +76,6 @@ protected:
void ReadCoreValues(); void ReadCoreValues();
void ReadDataStorageValues(); void ReadDataStorageValues();
void ReadDebuggingValues(); void ReadDebuggingValues();
#ifdef __unix__
void ReadLinuxValues();
#endif
void ReadServiceValues(); void ReadServiceValues();
void ReadDisabledAddOnValues(); void ReadDisabledAddOnValues();
void ReadMiscellaneousValues(); void ReadMiscellaneousValues();
@ -110,9 +107,6 @@ protected:
void SaveCoreValues(); void SaveCoreValues();
void SaveDataStorageValues(); void SaveDataStorageValues();
void SaveDebuggingValues(); void SaveDebuggingValues();
#ifdef __unix__
void SaveLinuxValues();
#endif
void SaveNetworkValues(); void SaveNetworkValues();
void SaveDisabledAddOnValues(); void SaveDisabledAddOnValues();
void SaveMiscellaneousValues(); void SaveMiscellaneousValues();

View File

@ -96,7 +96,6 @@ add_library(hid_core STATIC
resources/system_buttons/home_button.h resources/system_buttons/home_button.h
resources/system_buttons/sleep_button.cpp resources/system_buttons/sleep_button.cpp
resources/system_buttons/sleep_button.h resources/system_buttons/sleep_button.h
resources/system_buttons/system_button_types.h
resources/touch_screen/gesture.cpp resources/touch_screen/gesture.cpp
resources/touch_screen/gesture.h resources/touch_screen/gesture.h
resources/touch_screen/gesture_types.h resources/touch_screen/gesture_types.h

View File

@ -422,10 +422,7 @@ struct NpadPowerInfo {
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
struct LedPattern { struct LedPattern {
LedPattern() { explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
raw = 0;
}
LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
position1.Assign(light1); position1.Assign(light1);
position2.Assign(light2); position2.Assign(light2);
position3.Assign(light3); position3.Assign(light3);
@ -440,16 +437,6 @@ struct LedPattern {
}; };
}; };
struct SleepButtonState {
union {
u64 raw{};
// Buttons
BitField<0, 1, u64> sleep;
};
};
static_assert(sizeof(SleepButtonState) == 0x8, "SleepButtonState has incorrect size.");
struct HomeButtonState { struct HomeButtonState {
union { union {
u64 raw{}; u64 raw{};

View File

@ -184,7 +184,7 @@ void ResourceManager::InitializeHidCommonSampler() {
keyboard->SetAppletResource(applet_resource, &shared_mutex); keyboard->SetAppletResource(applet_resource, &shared_mutex);
const auto settings = const auto settings =
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys");
npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings); npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings);
six_axis->SetAppletResource(applet_resource, &shared_mutex); six_axis->SetAppletResource(applet_resource, &shared_mutex);

View File

@ -8,8 +8,7 @@
namespace Service::HID { namespace Service::HID {
HidFirmwareSettings::HidFirmwareSettings(Core::System& system) { HidFirmwareSettings::HidFirmwareSettings(Core::System& system) {
m_set_sys = m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys");
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
LoadSettings(true); LoadSettings(true);
} }

View File

@ -956,6 +956,17 @@ Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1,
return ResultSuccess; return ResultSuccess;
} }
Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return ResultInvalidNpadId;
}
const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device;
pattern = controller->GetLedPattern();
return ResultSuccess;
}
Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
Core::HID::NpadIdType npad_id) const { Core::HID::NpadIdType npad_id) const {
std::scoped_lock lock{mutex}; std::scoped_lock lock{mutex};

View File

@ -97,6 +97,8 @@ public:
Result ResetIsSixAxisSensorDeviceNewlyAssigned( Result ResetIsSixAxisSensorDeviceNewlyAssigned(
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle);
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
Core::HID::NpadIdType npad_id) const; Core::HID::NpadIdType npad_id) const;
Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id,

View File

@ -12,7 +12,6 @@
#include "hid_core/resources/mouse/mouse_types.h" #include "hid_core/resources/mouse/mouse_types.h"
#include "hid_core/resources/npad/npad_types.h" #include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/ring_lifo.h" #include "hid_core/resources/ring_lifo.h"
#include "hid_core/resources/system_buttons/system_button_types.h"
#include "hid_core/resources/touch_screen/touch_types.h" #include "hid_core/resources/touch_screen/touch_types.h"
namespace Service::HID { namespace Service::HID {
@ -76,24 +75,24 @@ static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000,
// This is nn::hid::detail::HomeButtonSharedMemoryFormat // This is nn::hid::detail::HomeButtonSharedMemoryFormat
struct HomeButtonSharedMemoryFormat { struct HomeButtonSharedMemoryFormat {
Lifo<HomeButtonState, HidEntryCount> home_lifo{}; CommonHeader header;
INSERT_PADDING_BYTES(0x48); INSERT_PADDING_BYTES(0x1E0);
}; };
static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200,
"HomeButtonSharedMemoryFormat is an invalid size"); "HomeButtonSharedMemoryFormat is an invalid size");
// This is nn::hid::detail::SleepButtonSharedMemoryFormat // This is nn::hid::detail::SleepButtonSharedMemoryFormat
struct SleepButtonSharedMemoryFormat { struct SleepButtonSharedMemoryFormat {
Lifo<SleepButtonState, HidEntryCount> sleep_lifo{}; CommonHeader header;
INSERT_PADDING_BYTES(0x48); INSERT_PADDING_BYTES(0x1E0);
}; };
static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200,
"SleepButtonSharedMemoryFormat is an invalid size"); "SleepButtonSharedMemoryFormat is an invalid size");
// This is nn::hid::detail::CaptureButtonSharedMemoryFormat // This is nn::hid::detail::CaptureButtonSharedMemoryFormat
struct CaptureButtonSharedMemoryFormat { struct CaptureButtonSharedMemoryFormat {
Lifo<CaptureButtonState, HidEntryCount> capture_lifo{}; CommonHeader header;
INSERT_PADDING_BYTES(0x48); INSERT_PADDING_BYTES(0x1E0);
}; };
static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200,
"CaptureButtonSharedMemoryFormat is an invalid size"); "CaptureButtonSharedMemoryFormat is an invalid size");

View File

@ -2,8 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core_timing.h" #include "core/core_timing.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "hid_core/resources/applet_resource.h" #include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/shared_memory_format.h" #include "hid_core/resources/shared_memory_format.h"
#include "hid_core/resources/system_buttons/capture_button.h" #include "hid_core/resources/system_buttons/capture_button.h"
@ -19,6 +17,10 @@ void CaptureButton::OnInit() {}
void CaptureButton::OnRelease() {} void CaptureButton::OnRelease() {}
void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!smart_update) {
return;
}
std::scoped_lock shared_lock{*shared_mutex}; std::scoped_lock shared_lock{*shared_mutex};
const u64 aruid = applet_resource->GetActiveAruid(); const u64 aruid = applet_resource->GetActiveAruid();
auto* data = applet_resource->GetAruidData(aruid); auto* data = applet_resource->GetAruidData(aruid);
@ -27,21 +29,11 @@ void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
return; return;
} }
auto& shared_memory = data->shared_memory_format->capture_button; auto& header = data->shared_memory_format->capture_button.header;
header.timestamp = core_timing.GetGlobalTimeNs().count();
if (!IsControllerActivated()) { header.total_entry_count = 17;
shared_memory.capture_lifo.buffer_count = 0; header.entry_count = 0;
shared_memory.capture_lifo.buffer_tail = 0; header.last_entry_index = 0;
return;
}
const auto& last_entry = shared_memory.capture_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
next_state.buttons.raw = controller->GetHomeButtons().raw;
shared_memory.capture_lifo.WriteNextEntry(next_state);
} }
} // namespace Service::HID } // namespace Service::HID

View File

@ -4,7 +4,6 @@
#pragma once #pragma once
#include "hid_core/resources/controller_base.h" #include "hid_core/resources/controller_base.h"
#include "hid_core/resources/system_buttons/system_button_types.h"
namespace Service::HID { namespace Service::HID {
@ -23,6 +22,6 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private: private:
CaptureButtonState next_state{}; bool smart_update{};
}; };
} // namespace Service::HID } // namespace Service::HID

View File

@ -2,8 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core_timing.h" #include "core/core_timing.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "hid_core/resources/applet_resource.h" #include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/shared_memory_format.h" #include "hid_core/resources/shared_memory_format.h"
#include "hid_core/resources/system_buttons/home_button.h" #include "hid_core/resources/system_buttons/home_button.h"
@ -19,6 +17,10 @@ void HomeButton::OnInit() {}
void HomeButton::OnRelease() {} void HomeButton::OnRelease() {}
void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!smart_update) {
return;
}
std::scoped_lock shared_lock{*shared_mutex}; std::scoped_lock shared_lock{*shared_mutex};
const u64 aruid = applet_resource->GetActiveAruid(); const u64 aruid = applet_resource->GetActiveAruid();
auto* data = applet_resource->GetAruidData(aruid); auto* data = applet_resource->GetAruidData(aruid);
@ -27,21 +29,11 @@ void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
return; return;
} }
auto& shared_memory = data->shared_memory_format->home_button; auto& header = data->shared_memory_format->home_button.header;
header.timestamp = core_timing.GetGlobalTimeNs().count();
if (!IsControllerActivated()) { header.total_entry_count = 17;
shared_memory.home_lifo.buffer_count = 0; header.entry_count = 0;
shared_memory.home_lifo.buffer_tail = 0; header.last_entry_index = 0;
return;
}
const auto& last_entry = shared_memory.home_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
next_state.buttons.raw = controller->GetHomeButtons().raw;
shared_memory.home_lifo.WriteNextEntry(next_state);
} }
} // namespace Service::HID } // namespace Service::HID

View File

@ -4,7 +4,6 @@
#pragma once #pragma once
#include "hid_core/resources/controller_base.h" #include "hid_core/resources/controller_base.h"
#include "hid_core/resources/system_buttons/system_button_types.h"
namespace Service::HID { namespace Service::HID {
@ -23,6 +22,6 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private: private:
HomeButtonState next_state{}; bool smart_update{};
}; };
} // namespace Service::HID } // namespace Service::HID

View File

@ -17,6 +17,10 @@ void SleepButton::OnInit() {}
void SleepButton::OnRelease() {} void SleepButton::OnRelease() {}
void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!smart_update) {
return;
}
std::scoped_lock shared_lock{*shared_mutex}; std::scoped_lock shared_lock{*shared_mutex};
const u64 aruid = applet_resource->GetActiveAruid(); const u64 aruid = applet_resource->GetActiveAruid();
auto* data = applet_resource->GetAruidData(aruid); auto* data = applet_resource->GetAruidData(aruid);
@ -25,20 +29,11 @@ void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
return; return;
} }
auto& shared_memory = data->shared_memory_format->sleep_button; auto& header = data->shared_memory_format->capture_button.header;
header.timestamp = core_timing.GetGlobalTimeNs().count();
if (!IsControllerActivated()) { header.total_entry_count = 17;
shared_memory.sleep_lifo.buffer_count = 0; header.entry_count = 0;
shared_memory.sleep_lifo.buffer_tail = 0; header.last_entry_index = 0;
return;
}
const auto& last_entry = shared_memory.sleep_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
next_state.buttons.raw = 0;
shared_memory.sleep_lifo.WriteNextEntry(next_state);
} }
} // namespace Service::HID } // namespace Service::HID

Some files were not shown because too many files have changed in this diff Show More