diff options
Diffstat (limited to 'src/core')
42 files changed, 955 insertions, 276 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 740c5b0fd..5629980d9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -530,6 +530,11 @@ add_library(core STATIC hle/service/ncm/ncm.h hle/service/nfc/nfc.cpp hle/service/nfc/nfc.h + hle/service/nfc/nfc_device.cpp + hle/service/nfc/nfc_device.h + hle/service/nfc/nfc_result.h + hle/service/nfc/nfc_user.cpp + hle/service/nfc/nfc_user.h hle/service/nfp/amiibo_crypto.cpp hle/service/nfp/amiibo_crypto.h hle/service/nfp/nfp.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index d8934be52..94d4e2212 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -189,7 +189,7 @@ struct System::Impl { kernel.Suspend(false); core_timing.SyncPause(false); - is_paused = false; + is_paused.store(false, std::memory_order_relaxed); return status; } @@ -200,14 +200,13 @@ struct System::Impl { core_timing.SyncPause(true); kernel.Suspend(true); - is_paused = true; + is_paused.store(true, std::memory_order_relaxed); return status; } bool IsPaused() const { - std::unique_lock lk(suspend_guard); - return is_paused; + return is_paused.load(std::memory_order_relaxed); } std::unique_lock<std::mutex> StallProcesses() { @@ -218,7 +217,7 @@ struct System::Impl { } void UnstallProcesses() { - if (!is_paused) { + if (!IsPaused()) { core_timing.SyncPause(false); kernel.Suspend(false); } @@ -465,7 +464,7 @@ struct System::Impl { } mutable std::mutex suspend_guard; - bool is_paused{}; + std::atomic_bool is_paused{}; std::atomic<bool> is_shutting_down{}; Timing::CoreTiming core_timing; diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 443323390..65a9fe802 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -578,18 +578,18 @@ KeyManager::KeyManager() { if (Settings::values.use_dev_keys) { dev_mode = true; - LoadFromFile(yuzu_keys_dir / "dev.keys", false); LoadFromFile(yuzu_keys_dir / "dev.keys_autogenerated", false); + LoadFromFile(yuzu_keys_dir / "dev.keys", false); } else { dev_mode = false; - LoadFromFile(yuzu_keys_dir / "prod.keys", false); LoadFromFile(yuzu_keys_dir / "prod.keys_autogenerated", false); + LoadFromFile(yuzu_keys_dir / "prod.keys", false); } - LoadFromFile(yuzu_keys_dir / "title.keys", true); LoadFromFile(yuzu_keys_dir / "title.keys_autogenerated", true); - LoadFromFile(yuzu_keys_dir / "console.keys", false); + LoadFromFile(yuzu_keys_dir / "title.keys", true); LoadFromFile(yuzu_keys_dir / "console.keys_autogenerated", false); + LoadFromFile(yuzu_keys_dir / "console.keys", false); } static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index ac1906d5e..95363b645 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -17,6 +17,8 @@ enum class WindowSystemType { Windows, X11, Wayland, + Cocoa, + Android, }; /** diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index fb7e5802a..b6c8cc58d 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -68,7 +68,7 @@ void EmulatedConsole::ReloadInput() { // If you load any device here add the equivalent to the UnloadInput() function SetTouchParams(); - motion_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(motion_params); + motion_devices = Common::Input::CreateInputDevice(motion_params); if (motion_devices) { motion_devices->SetCallback({ .on_change = @@ -79,7 +79,7 @@ void EmulatedConsole::ReloadInput() { // Unique index for identifying touch device source std::size_t index = 0; for (auto& touch_device : touch_devices) { - touch_device = Common::Input::CreateDevice<Common::Input::InputDevice>(touch_params[index]); + touch_device = Common::Input::CreateInputDevice(touch_params[index]); if (!touch_device) { continue; } diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index ec1364452..c96d9eef3 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include <algorithm> + #include "common/thread.h" #include "core/hid/emulated_controller.h" #include "core/hid/input_converter.h" @@ -144,29 +146,23 @@ void EmulatedController::LoadDevices() { LoadTASParams(); - std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, - button_params.begin() + Settings::NativeButton::BUTTON_NS_END, - button_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); - std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, - stick_params.begin() + Settings::NativeAnalog::STICK_HID_END, - stick_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); - std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, - motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, - motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); - std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), - Common::Input::CreateDevice<Common::Input::InputDevice>); - std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(), - Common::Input::CreateDevice<Common::Input::InputDevice>); - camera_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(camera_params); - nfc_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(nfc_params); - std::transform(output_params.begin(), output_params.end(), output_devices.begin(), - Common::Input::CreateDevice<Common::Input::OutputDevice>); + std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice); + std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice); + std::ranges::transform(motion_params, motion_devices.begin(), Common::Input::CreateInputDevice); + std::ranges::transform(trigger_params, trigger_devices.begin(), + Common::Input::CreateInputDevice); + std::ranges::transform(battery_params, battery_devices.begin(), + Common::Input::CreateInputDevice); + camera_devices = Common::Input::CreateInputDevice(camera_params); + nfc_devices = Common::Input::CreateInputDevice(nfc_params); + std::ranges::transform(output_params, output_devices.begin(), + Common::Input::CreateOutputDevice); // Initialize TAS devices - std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), - Common::Input::CreateDevice<Common::Input::InputDevice>); - std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(), - Common::Input::CreateDevice<Common::Input::InputDevice>); + std::ranges::transform(tas_button_params, tas_button_devices.begin(), + Common::Input::CreateInputDevice); + std::ranges::transform(tas_stick_params, tas_stick_devices.begin(), + Common::Input::CreateInputDevice); } void EmulatedController::LoadTASParams() { diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 8d367b546..e421828d2 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -25,12 +25,12 @@ void EmulatedDevices::ReloadInput() { Common::ParamPackage mouse_params; mouse_params.Set("engine", "mouse"); mouse_params.Set("button", static_cast<int>(key_index)); - mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params); + mouse_device = Common::Input::CreateInputDevice(mouse_params); key_index++; } - mouse_stick_device = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( - "engine:mouse,axis_x:0,axis_y:1"); + mouse_stick_device = + Common::Input::CreateInputDeviceFromString("engine:mouse,axis_x:0,axis_y:1"); // First two axis are reserved for mouse position key_index = 2; @@ -38,7 +38,7 @@ void EmulatedDevices::ReloadInput() { Common::ParamPackage mouse_params; mouse_params.Set("engine", "mouse"); mouse_params.Set("axis", static_cast<int>(key_index)); - mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params); + mouse_device = Common::Input::CreateInputDevice(mouse_params); key_index++; } @@ -50,7 +50,7 @@ void EmulatedDevices::ReloadInput() { keyboard_params.Set("button", static_cast<int>(key_index)); keyboard_params.Set("port", 1); keyboard_params.Set("pad", 0); - keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params); + keyboard_device = Common::Input::CreateInputDevice(keyboard_params); key_index++; } @@ -62,11 +62,11 @@ void EmulatedDevices::ReloadInput() { keyboard_params.Set("button", static_cast<int>(key_index)); keyboard_params.Set("port", 1); keyboard_params.Set("pad", 1); - keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params); + keyboard_device = Common::Input::CreateInputDevice(keyboard_params); key_index++; } - ring_analog_device = Common::Input::CreateDevice<Common::Input::InputDevice>(ring_params); + ring_analog_device = Common::Input::CreateInputDevice(ring_params); for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) { if (!mouse_button_devices[index]) { @@ -145,6 +145,7 @@ void EmulatedDevices::UnloadInput() { for (auto& button : keyboard_modifier_devices) { button.reset(); } + ring_analog_device.reset(); } void EmulatedDevices::EnableConfiguration() { diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index d87be72d6..e252b5f4b 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -199,7 +199,7 @@ public: ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. - u32* CommandBuffer() { + [[nodiscard]] u32* CommandBuffer() { return cmd_buf.data(); } @@ -207,7 +207,7 @@ public: * Returns the session through which this request was made. This can be used as a map key to * access per-client data on services. */ - Kernel::KServerSession* Session() { + [[nodiscard]] Kernel::KServerSession* Session() { return server_session; } @@ -217,61 +217,61 @@ public: /// Writes data from this context back to the requesting process/thread. Result WriteToOutgoingCommandBuffer(KThread& requesting_thread); - u32_le GetHipcCommand() const { + [[nodiscard]] u32_le GetHipcCommand() const { return command; } - u32_le GetTipcCommand() const { + [[nodiscard]] u32_le GetTipcCommand() const { return static_cast<u32_le>(command_header->type.Value()) - static_cast<u32_le>(IPC::CommandType::TIPC_CommandRegion); } - u32_le GetCommand() const { + [[nodiscard]] u32_le GetCommand() const { return command_header->IsTipc() ? GetTipcCommand() : GetHipcCommand(); } - bool IsTipc() const { + [[nodiscard]] bool IsTipc() const { return command_header->IsTipc(); } - IPC::CommandType GetCommandType() const { + [[nodiscard]] IPC::CommandType GetCommandType() const { return command_header->type; } - u64 GetPID() const { + [[nodiscard]] u64 GetPID() const { return pid; } - u32 GetDataPayloadOffset() const { + [[nodiscard]] u32 GetDataPayloadOffset() const { return data_payload_offset; } - const std::vector<IPC::BufferDescriptorX>& BufferDescriptorX() const { + [[nodiscard]] const std::vector<IPC::BufferDescriptorX>& BufferDescriptorX() const { return buffer_x_desciptors; } - const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorA() const { + [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorA() const { return buffer_a_desciptors; } - const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorB() const { + [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorB() const { return buffer_b_desciptors; } - const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { + [[nodiscard]] const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { return buffer_c_desciptors; } - const IPC::DomainMessageHeader& GetDomainMessageHeader() const { + [[nodiscard]] const IPC::DomainMessageHeader& GetDomainMessageHeader() const { return domain_message_header.value(); } - bool HasDomainMessageHeader() const { + [[nodiscard]] bool HasDomainMessageHeader() const { return domain_message_header.has_value(); } /// Helper function to read a buffer using the appropriate buffer descriptor - std::vector<u8> ReadBuffer(std::size_t buffer_index = 0) const; + [[nodiscard]] std::vector<u8> ReadBuffer(std::size_t buffer_index = 0) const; /// Helper function to write a buffer using the appropriate buffer descriptor std::size_t WriteBuffer(const void* buffer, std::size_t size, @@ -308,22 +308,34 @@ public: } /// Helper function to get the size of the input buffer - std::size_t GetReadBufferSize(std::size_t buffer_index = 0) const; + [[nodiscard]] std::size_t GetReadBufferSize(std::size_t buffer_index = 0) const; /// Helper function to get the size of the output buffer - std::size_t GetWriteBufferSize(std::size_t buffer_index = 0) const; + [[nodiscard]] std::size_t GetWriteBufferSize(std::size_t buffer_index = 0) const; + + /// Helper function to derive the number of elements able to be contained in the read buffer + template <typename T> + [[nodiscard]] std::size_t GetReadBufferNumElements(std::size_t buffer_index = 0) const { + return GetReadBufferSize(buffer_index) / sizeof(T); + } + + /// Helper function to derive the number of elements able to be contained in the write buffer + template <typename T> + [[nodiscard]] std::size_t GetWriteBufferNumElements(std::size_t buffer_index = 0) const { + return GetWriteBufferSize(buffer_index) / sizeof(T); + } /// Helper function to test whether the input buffer at buffer_index can be read - bool CanReadBuffer(std::size_t buffer_index = 0) const; + [[nodiscard]] bool CanReadBuffer(std::size_t buffer_index = 0) const; /// Helper function to test whether the output buffer at buffer_index can be written - bool CanWriteBuffer(std::size_t buffer_index = 0) const; + [[nodiscard]] bool CanWriteBuffer(std::size_t buffer_index = 0) const; - Handle GetCopyHandle(std::size_t index) const { + [[nodiscard]] Handle GetCopyHandle(std::size_t index) const { return incoming_copy_handles.at(index); } - Handle GetMoveHandle(std::size_t index) const { + [[nodiscard]] Handle GetMoveHandle(std::size_t index) const { return incoming_move_handles.at(index); } @@ -348,13 +360,13 @@ public: manager = manager_; } - std::string Description() const; + [[nodiscard]] std::string Description() const; - KThread& GetThread() { + [[nodiscard]] KThread& GetThread() { return *thread; } - std::shared_ptr<SessionRequestManager> GetManager() const { + [[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const { return manager.lock(); } diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 1c7a766c8..3535ddc0c 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/kernel/k_handle_table.h" +#include "core/hle/kernel/k_process.h" namespace Kernel { @@ -82,6 +83,22 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { R_SUCCEED(); } +KScopedAutoObject<KAutoObject> KHandleTable::GetObjectForIpc(Handle handle, + KThread* cur_thread) const { + // Handle pseudo-handles. + ASSERT(cur_thread != nullptr); + if (handle == Svc::PseudoHandle::CurrentProcess) { + auto* const cur_process = cur_thread->GetOwnerProcess(); + ASSERT(cur_process != nullptr); + return cur_process; + } + if (handle == Svc::PseudoHandle::CurrentThread) { + return cur_thread; + } + + return GetObjectForIpcWithoutPseudoHandle(handle); +} + Result KHandleTable::Reserve(Handle* out_handle) { KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 65cae3b27..37a24e7d9 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h @@ -113,21 +113,7 @@ public: return this->GetObjectImpl(handle); } - KScopedAutoObject<KAutoObject> GetObjectForIpc(Handle handle, KThread* cur_thread) const { - // Handle pseudo-handles. - ASSERT(cur_thread != nullptr); - if (handle == Svc::PseudoHandle::CurrentProcess) { - auto* const cur_process = - static_cast<KAutoObject*>(static_cast<void*>(cur_thread->GetOwnerProcess())); - ASSERT(cur_process != nullptr); - return cur_process; - } - if (handle == Svc::PseudoHandle::CurrentThread) { - return static_cast<KAutoObject*>(cur_thread); - } - - return GetObjectForIpcWithoutPseudoHandle(handle); - } + KScopedAutoObject<KAutoObject> GetObjectForIpc(Handle handle, KThread* cur_thread) const; KScopedAutoObject<KAutoObject> GetObjectByIndex(Handle* out_handle, size_t index) const { KScopedDisableDispatch dd{m_kernel}; diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index 608925dfc..053e8f9dd 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp @@ -122,10 +122,10 @@ private: } void GetReleasedAudioInBuffer(Kernel::HLERequestContext& ctx) { - auto write_buffer_size = ctx.GetWriteBufferSize() / sizeof(u64); - std::vector<u64> released_buffers(write_buffer_size, 0); + const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); + std::vector<u64> released_buffers(write_buffer_size); - auto count = impl->GetReleasedBuffers(released_buffers); + const auto count = impl->GetReleasedBuffers(released_buffers); [[maybe_unused]] std::string tags{}; for (u32 i = 0; i < count; i++) { @@ -228,7 +228,7 @@ void AudInU::ListAudioIns(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); const auto write_count = - static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(AudioDevice::AudioDeviceName)); + static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>()); std::vector<AudioDevice::AudioDeviceName> device_names{}; u32 out_count{0}; @@ -248,7 +248,7 @@ void AudInU::ListAudioInsAutoFiltered(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); const auto write_count = - static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(AudioDevice::AudioDeviceName)); + static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>()); std::vector<AudioDevice::AudioDeviceName> device_names{}; u32 out_count{0}; diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 122290c6a..29751f075 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -129,16 +129,16 @@ private: } void GetReleasedAudioOutBuffers(Kernel::HLERequestContext& ctx) { - auto write_buffer_size = ctx.GetWriteBufferSize() / sizeof(u64); - std::vector<u64> released_buffers(write_buffer_size, 0); + const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); + std::vector<u64> released_buffers(write_buffer_size); - auto count = impl->GetReleasedBuffers(released_buffers); + const auto count = impl->GetReleasedBuffers(released_buffers); [[maybe_unused]] std::string tags{}; for (u32 i = 0; i < count; i++) { tags += fmt::format("{:08X}, ", released_buffers[i]); } - [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()}; + [[maybe_unused]] const auto sessionid{impl->GetSystem().GetSessionId()}; LOG_TRACE(Service_Audio, "called. Session {} released {} buffers: {}", sessionid, count, tags); @@ -244,7 +244,7 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { std::scoped_lock l{impl->mutex}; const auto write_count = - static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(AudioDevice::AudioDeviceName)); + static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>()); std::vector<AudioDevice::AudioDeviceName> device_names{}; if (write_count > 0) { device_names.emplace_back("DeviceOut"); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 77431e743..3a1c231b6 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -275,7 +275,7 @@ public: private: void ListAudioDeviceName(Kernel::HLERequestContext& ctx) { - const size_t in_count = ctx.GetWriteBufferSize() / sizeof(AudioDevice::AudioDeviceName); + const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>(); std::vector<AudioDevice::AudioDeviceName> out_names{}; @@ -336,7 +336,7 @@ private: } void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) { - const auto write_size = ctx.GetWriteBufferSize() / sizeof(char); + const auto write_size = ctx.GetWriteBufferSize(); std::string out_name{"AudioTvOutput"}; LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name); @@ -388,7 +388,7 @@ private: } void ListAudioOutputDeviceName(Kernel::HLERequestContext& ctx) { - const size_t in_count = ctx.GetWriteBufferSize() / sizeof(AudioDevice::AudioDeviceName); + const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>(); std::vector<AudioDevice::AudioDeviceName> out_names{}; diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 8bafc3a98..825fb8bcc 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -68,7 +68,7 @@ private: ExtraBehavior extra_behavior) { u32 consumed = 0; u32 sample_count = 0; - std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16)); + std::vector<opus_int16> samples(ctx.GetWriteBufferNumElements<opus_int16>()); if (extra_behavior == ExtraBehavior::ResetContext) { ResetDecoderContext(); diff --git a/src/core/hle/service/bcat/bcat_module.cpp b/src/core/hle/service/bcat/bcat_module.cpp index bc08ac487..cbe690a5d 100644 --- a/src/core/hle/service/bcat/bcat_module.cpp +++ b/src/core/hle/service/bcat/bcat_module.cpp @@ -443,7 +443,7 @@ private: } void Read(Kernel::HLERequestContext& ctx) { - auto write_size = ctx.GetWriteBufferSize() / sizeof(DeliveryCacheDirectoryEntry); + auto write_size = ctx.GetWriteBufferNumElements<DeliveryCacheDirectoryEntry>(); LOG_DEBUG(Service_BCAT, "called, write_size={:016X}", write_size); @@ -533,7 +533,7 @@ private: } void EnumerateDeliveryCacheDirectory(Kernel::HLERequestContext& ctx) { - auto size = ctx.GetWriteBufferSize() / sizeof(DirectoryName); + auto size = ctx.GetWriteBufferNumElements<DirectoryName>(); LOG_DEBUG(Service_BCAT, "called, size={:016X}", size); diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index ff9b0427c..d183e5829 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp @@ -192,12 +192,10 @@ private: } void ListCommonTicketRightsIds(Kernel::HLERequestContext& ctx) { - u32 out_entries; - if (keys.GetCommonTickets().empty()) - out_entries = 0; - else - out_entries = static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(u128)); - + size_t out_entries = 0; + if (!keys.GetCommonTickets().empty()) { + out_entries = ctx.GetWriteBufferNumElements<u128>(); + } LOG_DEBUG(Service_ETicket, "called, entries={:016X}", out_entries); keys.PopulateTickets(); @@ -206,20 +204,19 @@ private: std::transform(tickets.begin(), tickets.end(), std::back_inserter(ids), [](const auto& pair) { return pair.first; }); - out_entries = static_cast<u32>(std::min<std::size_t>(ids.size(), out_entries)); + out_entries = std::min(ids.size(), out_entries); ctx.WriteBuffer(ids.data(), out_entries * sizeof(u128)); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push<u32>(out_entries); + rb.Push<u32>(static_cast<u32>(out_entries)); } void ListPersonalizedTicketRightsIds(Kernel::HLERequestContext& ctx) { - u32 out_entries; - if (keys.GetPersonalizedTickets().empty()) - out_entries = 0; - else - out_entries = static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(u128)); + size_t out_entries = 0; + if (!keys.GetPersonalizedTickets().empty()) { + out_entries = ctx.GetWriteBufferNumElements<u128>(); + } LOG_DEBUG(Service_ETicket, "called, entries={:016X}", out_entries); @@ -229,12 +226,12 @@ private: std::transform(tickets.begin(), tickets.end(), std::back_inserter(ids), [](const auto& pair) { return pair.first; }); - out_entries = static_cast<u32>(std::min<std::size_t>(ids.size(), out_entries)); + out_entries = std::min(ids.size(), out_entries); ctx.WriteBuffer(ids.data(), out_entries * sizeof(u128)); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push<u32>(out_entries); + rb.Push<u32>(static_cast<u32>(out_entries)); } void GetCommonTicketSize(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index c08274ef9..fbb16a7da 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -277,7 +277,7 @@ private: LOG_DEBUG(Service_FS, "called."); // Calculate how many entries we can fit in the output buffer - const u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); + const u64 count_entries = ctx.GetWriteBufferNumElements<FileSys::Entry>(); // Cap at total number of entries. const u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); @@ -543,7 +543,7 @@ public: LOG_DEBUG(Service_FS, "called"); // Calculate how many entries we can fit in the output buffer - const u64 count_entries = ctx.GetWriteBufferSize() / sizeof(SaveDataInfo); + const u64 count_entries = ctx.GetWriteBufferNumElements<SaveDataInfo>(); // Cap at total number of entries. const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index); diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index 6df563136..c49c61cff 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -292,7 +292,7 @@ public: void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) { const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0); - const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate); + const std::size_t node_buffer_count = ctx.GetWriteBufferNumElements<NodeLatestUpdate>(1); if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) { LOG_ERROR(Service_LDN, "Invalid buffer, size = {}, count = {}", network_buffer_size, @@ -333,7 +333,7 @@ public: const auto channel{rp.PopEnum<WifiChannel>()}; const auto scan_filter{rp.PopRaw<ScanFilter>()}; - const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo); + const std::size_t network_info_size = ctx.GetWriteBufferNumElements<NetworkInfo>(); if (network_info_size == 0) { LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size); diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 046c5f18f..2f4bacb3b 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp @@ -7,6 +7,7 @@ #include "common/settings.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/nfc/nfc.h" +#include "core/hle/service/nfc/nfc_user.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" @@ -97,76 +98,6 @@ private: } }; -class IUser final : public ServiceFramework<IUser> { -public: - explicit IUser(Core::System& system_) : ServiceFramework{system_, "NFC::IUser"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IUser::InitializeOld, "InitializeOld"}, - {1, &IUser::FinalizeOld, "FinalizeOld"}, - {2, &IUser::GetStateOld, "GetStateOld"}, - {3, &IUser::IsNfcEnabledOld, "IsNfcEnabledOld"}, - {400, &IUser::InitializeOld, "Initialize"}, - {401, &IUser::FinalizeOld, "Finalize"}, - {402, &IUser::GetStateOld, "GetState"}, - {403, &IUser::IsNfcEnabledOld, "IsNfcEnabled"}, - {404, nullptr, "ListDevices"}, - {405, nullptr, "GetDeviceState"}, - {406, nullptr, "GetNpadId"}, - {407, nullptr, "AttachAvailabilityChangeEvent"}, - {408, nullptr, "StartDetection"}, - {409, nullptr, "StopDetection"}, - {410, nullptr, "GetTagInfo"}, - {411, nullptr, "AttachActivateEvent"}, - {412, nullptr, "AttachDeactivateEvent"}, - {1000, nullptr, "ReadMifare"}, - {1001, nullptr, "WriteMifare"}, - {1300, nullptr, "SendCommandByPassThrough"}, - {1301, nullptr, "KeepPassThroughSession"}, - {1302, nullptr, "ReleasePassThroughSession"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - enum class NfcStates : u32 { - Finalized = 6, - }; - - void InitializeOld(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0}; - rb.Push(ResultSuccess); - // We don't deal with hardware initialization so we can just stub this. - } - - void IsNfcEnabledOld(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "IsNfcEnabledOld"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushRaw<u8>(true); - } - - void GetStateOld(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NFC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(NfcStates::Finalized); // TODO(ogniK): Figure out if this matches nfp - } - - void FinalizeOld(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NFC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } -}; - class NFC_U final : public ServiceFramework<NFC_U> { public: explicit NFC_U(Core::System& system_) : ServiceFramework{system_, "nfc:user"} { diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp new file mode 100644 index 000000000..4d514cf5f --- /dev/null +++ b/src/core/hle/service/nfc/nfc_device.cpp @@ -0,0 +1,197 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/input.h" +#include "common/logging/log.h" +#include "core/core.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/nfc/nfc_device.h" +#include "core/hle/service/nfc/nfc_result.h" +#include "core/hle/service/nfc/nfc_user.h" + +namespace Service::NFC { +NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, + KernelHelpers::ServiceContext& service_context_, + Kernel::KEvent* availability_change_event_) + : npad_id{npad_id_}, system{system_}, service_context{service_context_}, + availability_change_event{availability_change_event_} { + activate_event = service_context.CreateEvent("IUser:NFCActivateEvent"); + deactivate_event = service_context.CreateEvent("IUser:NFCDeactivateEvent"); + npad_device = system.HIDCore().GetEmulatedController(npad_id); + + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); }, + .is_npad_service = false, + }; + is_controller_set = true; + callback_key = npad_device->SetCallback(engine_callback); +} + +NfcDevice::~NfcDevice() { + activate_event->Close(); + deactivate_event->Close(); + if (!is_controller_set) { + return; + } + npad_device->DeleteCallback(callback_key); + is_controller_set = false; +}; + +void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { + if (type == Core::HID::ControllerTriggerType::Connected || + type == Core::HID::ControllerTriggerType::Disconnected) { + availability_change_event->Signal(); + return; + } + + if (type != Core::HID::ControllerTriggerType::Nfc) { + return; + } + + if (!npad_device->IsConnected()) { + return; + } + + const auto nfc_status = npad_device->GetNfc(); + switch (nfc_status.state) { + case Common::Input::NfcState::NewAmiibo: + LoadNfcTag(nfc_status.data); + break; + case Common::Input::NfcState::AmiiboRemoved: + if (device_state != NFP::DeviceState::SearchingForTag) { + CloseNfcTag(); + } + break; + default: + break; + } +} + +bool NfcDevice::LoadNfcTag(std::span<const u8> data) { + if (device_state != NFP::DeviceState::SearchingForTag) { + LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state); + return false; + } + + if (data.size() != sizeof(NFP::EncryptedNTAG215File)) { + LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); + return false; + } + + memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); + + device_state = NFP::DeviceState::TagFound; + deactivate_event->GetReadableEvent().Clear(); + activate_event->Signal(); + return true; +} + +void NfcDevice::CloseNfcTag() { + LOG_INFO(Service_NFC, "Remove nfc tag"); + + device_state = NFP::DeviceState::TagRemoved; + encrypted_tag_data = {}; + activate_event->GetReadableEvent().Clear(); + deactivate_event->Signal(); +} + +Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { + return activate_event->GetReadableEvent(); +} + +Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const { + return deactivate_event->GetReadableEvent(); +} + +void NfcDevice::Initialize() { + device_state = + npad_device->HasNfc() ? NFP::DeviceState::Initialized : NFP::DeviceState::Unavailable; + encrypted_tag_data = {}; +} + +void NfcDevice::Finalize() { + if (device_state == NFP::DeviceState::SearchingForTag || + device_state == NFP::DeviceState::TagRemoved) { + StopDetection(); + } + device_state = NFP::DeviceState::Unavailable; +} + +Result NfcDevice::StartDetection(s32 protocol_) { + if (device_state != NFP::DeviceState::Initialized && + device_state != NFP::DeviceState::TagRemoved) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + return WrongDeviceState; + } + + if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) { + LOG_ERROR(Service_NFC, "Nfc not supported"); + return NfcDisabled; + } + + device_state = NFP::DeviceState::SearchingForTag; + protocol = protocol_; + return ResultSuccess; +} + +Result NfcDevice::StopDetection() { + npad_device->SetPollingMode(Common::Input::PollingMode::Active); + + if (device_state == NFP::DeviceState::Initialized) { + return ResultSuccess; + } + + if (device_state == NFP::DeviceState::TagFound || + device_state == NFP::DeviceState::TagMounted) { + CloseNfcTag(); + return ResultSuccess; + } + if (device_state == NFP::DeviceState::SearchingForTag || + device_state == NFP::DeviceState::TagRemoved) { + device_state = NFP::DeviceState::Initialized; + return ResultSuccess; + } + + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + return WrongDeviceState; +} + +Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const { + if (device_state != NFP::DeviceState::TagFound && + device_state != NFP::DeviceState::TagMounted) { + LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); + if (device_state == NFP::DeviceState::TagRemoved) { + return TagRemoved; + } + return WrongDeviceState; + } + + // Protocol and tag type may change here + tag_info = { + .uuid = encrypted_tag_data.uuid.uid, + .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()), + .protocol = NFP::TagProtocol::TypeA, + .tag_type = NFP::TagType::Type2, + }; + + return ResultSuccess; +} + +u64 NfcDevice::GetHandle() const { + // Generate a handle based of the npad id + return static_cast<u64>(npad_id); +} + +NFP::DeviceState NfcDevice::GetCurrentState() const { + return device_state; +} + +Core::HID::NpadIdType NfcDevice::GetNpadId() const { + return npad_id; +} + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_device.h b/src/core/hle/service/nfc/nfc_device.h new file mode 100644 index 000000000..fa1348f1a --- /dev/null +++ b/src/core/hle/service/nfc/nfc_device.h @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nfp/nfp_types.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Core { +class System; +} // namespace Core + +namespace Core::HID { +class EmulatedController; +enum class ControllerTriggerType; +enum class NpadIdType : u32; +} // namespace Core::HID + +namespace Service::NFC { +class NfcDevice { +public: + NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, + KernelHelpers::ServiceContext& service_context_, + Kernel::KEvent* availability_change_event_); + ~NfcDevice(); + + void Initialize(); + void Finalize(); + + Result StartDetection(s32 protocol_); + Result StopDetection(); + + Result GetTagInfo(NFP::TagInfo& tag_info) const; + + u64 GetHandle() const; + NFP::DeviceState GetCurrentState() const; + Core::HID::NpadIdType GetNpadId() const; + + Kernel::KReadableEvent& GetActivateEvent() const; + Kernel::KReadableEvent& GetDeactivateEvent() const; + +private: + void NpadUpdate(Core::HID::ControllerTriggerType type); + bool LoadNfcTag(std::span<const u8> data); + void CloseNfcTag(); + + bool is_controller_set{}; + int callback_key; + const Core::HID::NpadIdType npad_id; + Core::System& system; + Core::HID::EmulatedController* npad_device = nullptr; + KernelHelpers::ServiceContext& service_context; + Kernel::KEvent* activate_event = nullptr; + Kernel::KEvent* deactivate_event = nullptr; + Kernel::KEvent* availability_change_event = nullptr; + + s32 protocol{}; + NFP::DeviceState device_state{NFP::DeviceState::Unavailable}; + + NFP::EncryptedNTAG215File encrypted_tag_data{}; +}; + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h new file mode 100644 index 000000000..537dc15f4 --- /dev/null +++ b/src/core/hle/service/nfc/nfc_result.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/result.h" + +namespace Service::NFC { + +constexpr Result DeviceNotFound(ErrorModule::NFC, 64); +constexpr Result InvalidArgument(ErrorModule::NFC, 65); +constexpr Result WrongDeviceState(ErrorModule::NFC, 73); +constexpr Result NfcDisabled(ErrorModule::NFC, 80); +constexpr Result TagRemoved(ErrorModule::NFC, 97); +constexpr Result CorruptedData(ErrorModule::NFC, 144); + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_user.cpp b/src/core/hle/service/nfc/nfc_user.cpp new file mode 100644 index 000000000..ced2d560b --- /dev/null +++ b/src/core/hle/service/nfc/nfc_user.cpp @@ -0,0 +1,365 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/hid/hid_types.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/nfc/nfc_device.h" +#include "core/hle/service/nfc/nfc_result.h" +#include "core/hle/service/nfc/nfc_user.h" +#include "core/hle/service/time/clock_types.h" + +namespace Service::NFC { + +IUser::IUser(Core::System& system_) + : ServiceFramework{system_, "NFC::IUser"}, service_context{system_, service_name} { + static const FunctionInfo functions[] = { + {0, &IUser::Initialize, "InitializeOld"}, + {1, &IUser::Finalize, "FinalizeOld"}, + {2, &IUser::GetState, "GetStateOld"}, + {3, &IUser::IsNfcEnabled, "IsNfcEnabledOld"}, + {400, &IUser::Initialize, "Initialize"}, + {401, &IUser::Finalize, "Finalize"}, + {402, &IUser::GetState, "GetState"}, + {403, &IUser::IsNfcEnabled, "IsNfcEnabled"}, + {404, &IUser::ListDevices, "ListDevices"}, + {405, &IUser::GetDeviceState, "GetDeviceState"}, + {406, &IUser::GetNpadId, "GetNpadId"}, + {407, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, + {408, &IUser::StartDetection, "StartDetection"}, + {409, &IUser::StopDetection, "StopDetection"}, + {410, &IUser::GetTagInfo, "GetTagInfo"}, + {411, &IUser::AttachActivateEvent, "AttachActivateEvent"}, + {412, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, + {1000, nullptr, "ReadMifare"}, + {1001, nullptr, "WriteMifare"}, + {1300, &IUser::SendCommandByPassThrough, "SendCommandByPassThrough"}, + {1301, nullptr, "KeepPassThroughSession"}, + {1302, nullptr, "ReleasePassThroughSession"}, + }; + RegisterHandlers(functions); + + availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent"); + + for (u32 device_index = 0; device_index < 10; device_index++) { + devices[device_index] = + std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, + service_context, availability_change_event); + } +} + +IUser ::~IUser() { + availability_change_event->Close(); +} + +void IUser::Initialize(Kernel::HLERequestContext& ctx) { + LOG_INFO(Service_NFC, "called"); + + state = State::Initialized; + + for (auto& device : devices) { + device->Initialize(); + } + + IPC::ResponseBuilder rb{ctx, 2, 0}; + rb.Push(ResultSuccess); +} + +void IUser::Finalize(Kernel::HLERequestContext& ctx) { + LOG_INFO(Service_NFC, "called"); + + state = State::NonInitialized; + + for (auto& device : devices) { + device->Finalize(); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IUser::GetState(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFC, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(state); +} + +void IUser::IsNfcEnabled(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFC, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(state != State::NonInitialized); +} + +void IUser::ListDevices(Kernel::HLERequestContext& ctx) { + LOG_INFO(Service_NFC, "called"); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + if (!ctx.CanWriteBuffer()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(InvalidArgument); + return; + } + + if (ctx.GetWriteBufferSize() == 0) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(InvalidArgument); + return; + } + + std::vector<u64> nfp_devices; + const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); + + for (auto& device : devices) { + if (nfp_devices.size() >= max_allowed_devices) { + continue; + } + if (device->GetCurrentState() != NFP::DeviceState::Unavailable) { + nfp_devices.push_back(device->GetHandle()); + } + } + + if (nfp_devices.empty()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + ctx.WriteBuffer(nfp_devices); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<s32>(nfp_devices.size())); +} + +void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(device.value()->GetCurrentState()); +} + +void IUser::GetNpadId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(device.value()->GetNpadId()); +} + +void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { + LOG_INFO(Service_NFC, "called"); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(availability_change_event->GetReadableEvent()); +} + +void IUser::StartDetection(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto nfp_protocol{rp.Pop<s32>()}; + LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + const auto result = device.value()->StartDetection(nfp_protocol); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void IUser::StopDetection(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + const auto result = device.value()->StopDetection(); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + NFP::TagInfo tag_info{}; + const auto result = device.value()->GetTagInfo(tag_info); + ctx.WriteBuffer(tag_info); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(device.value()->GetActivateEvent()); +} + +void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(device.value()->GetDeactivateEvent()); +} + +void IUser::SendCommandByPassThrough(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto device_handle{rp.Pop<u64>()}; + const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()}; + const auto command_data{ctx.ReadBuffer()}; + + LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}", + device_handle, timeout.ToSeconds(), command_data.size()); + + if (state == State::NonInitialized) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(NfcDisabled); + return; + } + + auto device = GetNfcDevice(device_handle); + + if (!device.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(DeviceNotFound); + return; + } + + std::vector<u8> out_data(1); + // TODO: Request data from nfc device + ctx.WriteBuffer(out_data); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<u32>(out_data.size())); +} + +std::optional<std::shared_ptr<NfcDevice>> IUser::GetNfcDevice(u64 handle) { + for (auto& device : devices) { + if (device->GetHandle() == handle) { + return device; + } + } + return std::nullopt; +} + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_user.h b/src/core/hle/service/nfc/nfc_user.h new file mode 100644 index 000000000..a5a4f12f9 --- /dev/null +++ b/src/core/hle/service/nfc/nfc_user.h @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <array> +#include <memory> +#include <optional> + +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/service.h" + +namespace Service::NFC { +class NfcDevice; + +class IUser final : public ServiceFramework<IUser> { +public: + explicit IUser(Core::System& system_); + ~IUser(); + +private: + enum class State : u32 { + NonInitialized, + Initialized, + }; + + void Initialize(Kernel::HLERequestContext& ctx); + void Finalize(Kernel::HLERequestContext& ctx); + void GetState(Kernel::HLERequestContext& ctx); + void IsNfcEnabled(Kernel::HLERequestContext& ctx); + void ListDevices(Kernel::HLERequestContext& ctx); + void GetDeviceState(Kernel::HLERequestContext& ctx); + void GetNpadId(Kernel::HLERequestContext& ctx); + void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx); + void StartDetection(Kernel::HLERequestContext& ctx); + void StopDetection(Kernel::HLERequestContext& ctx); + void GetTagInfo(Kernel::HLERequestContext& ctx); + void AttachActivateEvent(Kernel::HLERequestContext& ctx); + void AttachDeactivateEvent(Kernel::HLERequestContext& ctx); + void SendCommandByPassThrough(Kernel::HLERequestContext& ctx); + + std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); + + KernelHelpers::ServiceContext service_context; + + std::array<std::shared_ptr<NfcDevice>, 10> devices{}; + + State state{State::NonInitialized}; + Kernel::KEvent* availability_change_event; +}; + +} // namespace Service::NFC diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp index 167e29572..ffb2f959c 100644 --- a/src/core/hle/service/nfp/amiibo_crypto.cpp +++ b/src/core/hle/service/nfp/amiibo_crypto.cpp @@ -12,7 +12,6 @@ #include "common/fs/fs.h" #include "common/fs/path_util.h" #include "common/logging/log.h" -#include "core/hle/service/mii/mii_manager.h" #include "core/hle/service/nfp/amiibo_crypto.h" namespace Service::NFP::AmiiboCrypto { diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index e1bf90d7c..c860fd1a1 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -2,10 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <array> -#include <atomic> -#include "common/fs/file.h" -#include "common/fs/path_util.h" #include "common/input.h" #include "common/logging/log.h" #include "common/string_util.h" @@ -19,7 +16,6 @@ #include "core/hle/service/mii/mii_manager.h" #include "core/hle/service/mii/types.h" #include "core/hle/service/nfp/amiibo_crypto.h" -#include "core/hle/service/nfp/nfp.h" #include "core/hle/service/nfp/nfp_device.h" #include "core/hle/service/nfp/nfp_result.h" #include "core/hle/service/nfp/nfp_user.h" @@ -49,6 +45,8 @@ NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, } NfpDevice::~NfpDevice() { + activate_event->Close(); + deactivate_event->Close(); if (!is_controller_set) { return; } diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index 3d1cb4609..b6a46f2ac 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -3,11 +3,10 @@ #pragma once -#include <array> #include <span> #include <vector> -#include "common/common_funcs.h" +#include "common/common_types.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nfp/nfp_types.h" #include "core/hle/service/service.h" diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp index ac492cc27..49816b4c7 100644 --- a/src/core/hle/service/nfp/nfp_user.cpp +++ b/src/core/hle/service/nfp/nfp_user.cpp @@ -1,9 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <array> -#include <atomic> - #include "common/logging/log.h" #include "core/core.h" #include "core/hid/hid_types.h" @@ -55,8 +52,12 @@ IUser::IUser(Core::System& system_) } } +IUser ::~IUser() { + availability_change_event->Close(); +} + void IUser::Initialize(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); + LOG_INFO(Service_NFP, "called"); state = State::Initialized; @@ -64,7 +65,7 @@ void IUser::Initialize(Kernel::HLERequestContext& ctx) { device->Initialize(); } - IPC::ResponseBuilder rb{ctx, 2, 0}; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -103,9 +104,9 @@ void IUser::ListDevices(Kernel::HLERequestContext& ctx) { } std::vector<u64> nfp_devices; - const std::size_t max_allowed_devices = ctx.GetWriteBufferSize() / sizeof(u64); + const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); - for (auto& device : devices) { + for (const auto& device : devices) { if (nfp_devices.size() >= max_allowed_devices) { continue; } @@ -114,7 +115,7 @@ void IUser::ListDevices(Kernel::HLERequestContext& ctx) { } } - if (nfp_devices.size() == 0) { + if (nfp_devices.empty()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(DeviceNotFound); return; @@ -551,9 +552,9 @@ void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { } void IUser::GetState(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); + LOG_DEBUG(Service_NFP, "called"); - IPC::ResponseBuilder rb{ctx, 3, 0}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.PushEnum(state); } diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h index 47aff3695..7e9a90af8 100644 --- a/src/core/hle/service/nfp/nfp_user.h +++ b/src/core/hle/service/nfp/nfp_user.h @@ -3,6 +3,10 @@ #pragma once +#include <array> +#include <memory> +#include <optional> + #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/service.h" @@ -12,6 +16,7 @@ class NfpDevice; class IUser final : public ServiceFramework<IUser> { public: explicit IUser(Core::System& system_); + ~IUser(); private: enum class State : u32 { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index e3ef06481..4fa9f51a6 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -129,6 +129,9 @@ static_assert(sizeof(NifmNetworkProfileData) == 0x18E, "NifmNetworkProfileData has incorrect size."); #pragma pack(pop) +constexpr Result ResultPendingConnection{ErrorModule::NIFM, 111}; +constexpr Result ResultNetworkCommunicationDisabled{ErrorModule::NIFM, 1111}; + class IScanRequest final : public ServiceFramework<IScanRequest> { public: explicit IScanRequest(Core::System& system_) : ServiceFramework{system_, "IScanRequest"} { @@ -192,6 +195,10 @@ private: void Submit(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); + if (state == RequestState::NotSubmitted) { + UpdateState(RequestState::Pending); + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -201,19 +208,32 @@ private: IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - - if (Network::GetHostIPv4Address().has_value()) { - rb.PushEnum(RequestState::Connected); - } else { - rb.PushEnum(RequestState::NotSubmitted); - } + rb.PushEnum(state); } void GetResult(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); + const auto result = [this] { + const auto has_connection = Network::GetHostIPv4Address().has_value(); + switch (state) { + case RequestState::NotSubmitted: + return has_connection ? ResultSuccess : ResultNetworkCommunicationDisabled; + case RequestState::Pending: + if (has_connection) { + UpdateState(RequestState::Connected); + } else { + UpdateState(RequestState::Error); + } + return ResultPendingConnection; + case RequestState::Connected: + default: + return ResultSuccess; + } + }(); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { @@ -252,8 +272,15 @@ private: rb.Push<u32>(0); } + void UpdateState(RequestState new_state) { + state = new_state; + event1->Signal(); + } + KernelHelpers::ServiceContext service_context; + RequestState state; + Kernel::KEvent* event1; Kernel::KEvent* event2; }; diff --git a/src/core/hle/service/ns/iplatform_service_manager.cpp b/src/core/hle/service/ns/iplatform_service_manager.cpp index fd047ff26..1fab2f0dd 100644 --- a/src/core/hle/service/ns/iplatform_service_manager.cpp +++ b/src/core/hle/service/ns/iplatform_service_manager.cpp @@ -279,13 +279,10 @@ void IPlatformServiceManager::GetSharedFontInOrderOfPriority(Kernel::HLERequestC font_sizes.push_back(region.size); } - // Resize buffers if game requests smaller size output. - font_codes.resize( - std::min<std::size_t>(font_codes.size(), ctx.GetWriteBufferSize(0) / sizeof(u32))); - font_offsets.resize( - std::min<std::size_t>(font_offsets.size(), ctx.GetWriteBufferSize(1) / sizeof(u32))); - font_sizes.resize( - std::min<std::size_t>(font_sizes.size(), ctx.GetWriteBufferSize(2) / sizeof(u32))); + // Resize buffers if game requests smaller size output + font_codes.resize(std::min(font_codes.size(), ctx.GetWriteBufferNumElements<u32>(0))); + font_offsets.resize(std::min(font_offsets.size(), ctx.GetWriteBufferNumElements<u32>(1))); + font_sizes.resize(std::min(font_sizes.size(), ctx.GetWriteBufferNumElements<u32>(2))); ctx.WriteBuffer(font_codes, 0); ctx.WriteBuffer(font_offsets, 1); diff --git a/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp index eda2041a0..aba51d280 100644 --- a/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp @@ -28,13 +28,15 @@ SyncpointManager::SyncpointManager(Tegra::Host1x::Host1x& host1x_) : host1x{host SyncpointManager::~SyncpointManager() = default; u32 SyncpointManager::ReserveSyncpoint(u32 id, bool client_managed) { - if (syncpoints.at(id).reserved) { + auto& syncpoint = syncpoints.at(id); + + if (syncpoint.reserved) { ASSERT_MSG(false, "Requested syncpoint is in use"); return 0; } - syncpoints.at(id).reserved = true; - syncpoints.at(id).interface_managed = client_managed; + syncpoint.reserved = true; + syncpoint.interface_managed = client_managed; return id; } @@ -56,11 +58,12 @@ u32 SyncpointManager::AllocateSyncpoint(bool client_managed) { void SyncpointManager::FreeSyncpoint(u32 id) { std::lock_guard lock(reservation_lock); - ASSERT(syncpoints.at(id).reserved); - syncpoints.at(id).reserved = false; + auto& syncpoint = syncpoints.at(id); + ASSERT(syncpoint.reserved); + syncpoint.reserved = false; } -bool SyncpointManager::IsSyncpointAllocated(u32 id) { +bool SyncpointManager::IsSyncpointAllocated(u32 id) const { return (id <= SyncpointCount) && syncpoints[id].reserved; } @@ -69,7 +72,7 @@ bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) const { if (!syncpoint.reserved) { ASSERT(false); - return 0; + return false; } // If the interface manages counters then we don't keep track of the maximum value as it handles @@ -82,40 +85,51 @@ bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) const { } u32 SyncpointManager::IncrementSyncpointMaxExt(u32 id, u32 amount) { - if (!syncpoints.at(id).reserved) { + auto& syncpoint = syncpoints.at(id); + + if (!syncpoint.reserved) { ASSERT(false); return 0; } - return syncpoints.at(id).counter_max += amount; + return syncpoint.counter_max += amount; } u32 SyncpointManager::ReadSyncpointMinValue(u32 id) { - if (!syncpoints.at(id).reserved) { + auto& syncpoint = syncpoints.at(id); + + if (!syncpoint.reserved) { ASSERT(false); return 0; } - return syncpoints.at(id).counter_min; + return syncpoint.counter_min; } u32 SyncpointManager::UpdateMin(u32 id) { - if (!syncpoints.at(id).reserved) { + auto& syncpoint = syncpoints.at(id); + + if (!syncpoint.reserved) { ASSERT(false); return 0; } - syncpoints.at(id).counter_min = host1x.GetSyncpointManager().GetHostSyncpointValue(id); - return syncpoints.at(id).counter_min; + syncpoint.counter_min = host1x.GetSyncpointManager().GetHostSyncpointValue(id); + return syncpoint.counter_min; } NvFence SyncpointManager::GetSyncpointFence(u32 id) { - if (!syncpoints.at(id).reserved) { + auto& syncpoint = syncpoints.at(id); + + if (!syncpoint.reserved) { ASSERT(false); return NvFence{}; } - return {.id = static_cast<s32>(id), .value = syncpoints.at(id).counter_max}; + return { + .id = static_cast<s32>(id), + .value = syncpoint.counter_max, + }; } } // namespace Service::Nvidia::NvCore diff --git a/src/core/hle/service/nvdrv/core/syncpoint_manager.h b/src/core/hle/service/nvdrv/core/syncpoint_manager.h index b76ef9032..4f2cefae5 100644 --- a/src/core/hle/service/nvdrv/core/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.h @@ -44,7 +44,7 @@ public: /** * @brief Checks if the given syncpoint is both allocated and below the number of HW syncpoints */ - bool IsSyncpointAllocated(u32 id); + bool IsSyncpointAllocated(u32 id) const; /** * @brief Finds a free syncpoint and reserves it diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 9f4c7c99a..6fc8565c0 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -55,48 +55,40 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger Module::Module(Core::System& system) : container{system.Host1x()}, service_context{system, "nvdrv"}, events_interface{*this} { builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvhost_as_gpu>(system, *this, container); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvhost_as_gpu>(system, *this, container); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvhost-gpu"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvhost_gpu>(system, events_interface, container); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvhost_gpu>(system, events_interface, container); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvhost-ctrl-gpu"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvmap"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvmap>(system, container); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvmap>(system, container); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvdisp_disp0"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvdisp_disp0>(system, container); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvdisp_disp0>(system, container); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvhost-ctrl"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvhost-nvdec"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvhost_nvdec>(system, container); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvhost_nvdec>(system, container); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvhost-nvjpg"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = std::make_shared<Devices::nvhost_nvjpg>(system); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvhost_nvjpg>(system); + return open_files.emplace(fd, std::move(device)).first; }; builders["/dev/nvhost-vic"] = [this, &system](DeviceFD fd) { - std::shared_ptr<Devices::nvdevice> device = - std::make_shared<Devices::nvhost_vic>(system, container); - return open_files.emplace(fd, device).first; + auto device = std::make_shared<Devices::nvhost_vic>(system, container); + return open_files.emplace(fd, std::move(device)).first; }; } diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp index 6d2c92a2c..152bb5bdf 100644 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp +++ b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp @@ -39,7 +39,7 @@ Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseco return Status::NoError; } -Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, Fence& release_fence) { +Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, const Fence& release_fence) { std::scoped_lock lock{mutex}; if (const auto status = AddReleaseFenceLocked(item.buf, item.graphic_buffer, release_fence); diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.h b/src/core/hle/service/nvflinger/buffer_item_consumer.h index 69046233d..a5c655d9e 100644 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.h +++ b/src/core/hle/service/nvflinger/buffer_item_consumer.h @@ -22,7 +22,7 @@ public: explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer); Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, bool wait_for_fence = true); - Status ReleaseBuffer(const BufferItem& item, Fence& release_fence); + Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence); }; } // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp index 1ce67c771..0767e548d 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp @@ -169,7 +169,7 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_ return Status::NoInit; } - core->consumer_listener = consumer_listener; + core->consumer_listener = std::move(consumer_listener); core->consumer_controlled_by_app = controlled_by_app; return Status::NoError; diff --git a/src/core/hle/service/nvflinger/consumer_base.cpp b/src/core/hle/service/nvflinger/consumer_base.cpp index 5b9995854..982531e2d 100644 --- a/src/core/hle/service/nvflinger/consumer_base.cpp +++ b/src/core/hle/service/nvflinger/consumer_base.cpp @@ -83,7 +83,7 @@ Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseco } Status ConsumerBase::AddReleaseFenceLocked(s32 slot, - const std::shared_ptr<GraphicBuffer> graphic_buffer, + const std::shared_ptr<GraphicBuffer>& graphic_buffer, const Fence& fence) { LOG_DEBUG(Service_NVFlinger, "slot={}", slot); @@ -100,7 +100,7 @@ Status ConsumerBase::AddReleaseFenceLocked(s32 slot, } Status ConsumerBase::ReleaseBufferLocked(s32 slot, - const std::shared_ptr<GraphicBuffer> graphic_buffer) { + const std::shared_ptr<GraphicBuffer>& graphic_buffer) { // If consumer no longer tracks this graphic_buffer (we received a new // buffer on the same slot), the buffer producer is definitely no longer // tracking it. @@ -121,7 +121,7 @@ Status ConsumerBase::ReleaseBufferLocked(s32 slot, } bool ConsumerBase::StillTracking(s32 slot, - const std::shared_ptr<GraphicBuffer> graphic_buffer) const { + const std::shared_ptr<GraphicBuffer>& graphic_buffer) const { if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { return false; } diff --git a/src/core/hle/service/nvflinger/consumer_base.h b/src/core/hle/service/nvflinger/consumer_base.h index 90ba07f45..9a8a5f6bb 100644 --- a/src/core/hle/service/nvflinger/consumer_base.h +++ b/src/core/hle/service/nvflinger/consumer_base.h @@ -27,18 +27,18 @@ public: protected: explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); - virtual ~ConsumerBase(); + ~ConsumerBase() override; - virtual void OnFrameAvailable(const BufferItem& item) override; - virtual void OnFrameReplaced(const BufferItem& item) override; - virtual void OnBuffersReleased() override; - virtual void OnSidebandStreamChanged() override; + void OnFrameAvailable(const BufferItem& item) override; + void OnFrameReplaced(const BufferItem& item) override; + void OnBuffersReleased() override; + void OnSidebandStreamChanged() override; void FreeBufferLocked(s32 slot_index); Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); - Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer); - bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer) const; - Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer, + Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer); + bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer) const; + Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer, const Fence& fence); struct Slot final { diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index c3af12c90..d1cbadde4 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -307,8 +307,7 @@ void NVFlinger::Compose() { swap_interval = buffer.swap_interval; - auto fence = android::Fence::NoFence(); - layer.GetConsumer().ReleaseBuffer(buffer, fence); + layer.GetConsumer().ReleaseBuffer(buffer, android::Fence::NoFence()); } } diff --git a/src/core/hle/service/nvflinger/producer_listener.h b/src/core/hle/service/nvflinger/producer_listener.h index 1c4d5db0e..6bf8aaf1e 100644 --- a/src/core/hle/service/nvflinger/producer_listener.h +++ b/src/core/hle/service/nvflinger/producer_listener.h @@ -10,6 +10,7 @@ namespace Service::android { class IProducerListener { public: + virtual ~IProducerListener() = default; virtual void OnBufferReleased() = 0; }; diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index f761c2da4..4f1a8d6b7 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp @@ -83,7 +83,7 @@ void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t num_la } void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t max_entries) { - const std::size_t requested_amount = ctx.GetWriteBufferSize() / sizeof(LanguageCode); + const std::size_t requested_amount = ctx.GetWriteBufferNumElements<LanguageCode>(); const std::size_t max_amount = std::min(requested_amount, max_entries); const std::size_t copy_amount = std::min(available_language_codes.size(), max_amount); const std::size_t copy_size = copy_amount * sizeof(LanguageCode); |