From 6c045c9beb9c202fdea49274edd845fb2af491c3 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 13 Nov 2022 10:52:48 -0600 Subject: service: nfc: fix tagprotocol and implement GetApplicationAreaId --- src/core/hle/service/nfp/nfp_device.cpp | 33 +++++++++++++++++++++++++++++++-- src/core/hle/service/nfp/nfp_device.h | 6 ++++-- src/core/hle/service/nfp/nfp_types.h | 10 +++++++--- src/core/hle/service/nfp/nfp_user.cpp | 2 +- 4 files changed, 43 insertions(+), 8 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index b19672560..2f9dfa9c2 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -77,6 +77,9 @@ void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { LoadAmiibo(nfc_status.data); break; case Common::Input::NfcState::AmiiboRemoved: + if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { + break; + } if (device_state != DeviceState::SearchingForTag) { CloseAmiibo(); } @@ -97,6 +100,8 @@ bool NfpDevice::LoadAmiibo(std::span data) { return false; } + // TODO: Filter by allowed_protocols here + memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); device_state = DeviceState::TagFound; @@ -143,7 +148,7 @@ void NfpDevice::Finalize() { device_state = DeviceState::Unavailable; } -Result NfpDevice::StartDetection(s32 protocol_) { +Result NfpDevice::StartDetection([[maybe_unused]] TagProtocol allowed_protocol) { if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); return WrongDeviceState; @@ -155,7 +160,7 @@ Result NfpDevice::StartDetection(s32 protocol_) { } device_state = DeviceState::SearchingForTag; - protocol = protocol_; + allowed_protocols = allowed_protocol; return ResultSuccess; } @@ -469,6 +474,30 @@ Result NfpDevice::OpenApplicationArea(u32 access_id) { return ResultSuccess; } +Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const { + if (device_state != DeviceState::TagMounted) { + LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); + if (device_state == DeviceState::TagRemoved) { + return TagRemoved; + } + return WrongDeviceState; + } + + if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { + LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); + return WrongDeviceState; + } + + if (tag_data.settings.settings.appdata_initialized.Value() == 0) { + LOG_WARNING(Service_NFP, "Application area is not initialized"); + return ApplicationAreaIsNotInitialized; + } + + application_area_id = tag_data.application_area_id; + + return ResultSuccess; +} + Result NfpDevice::GetApplicationArea(std::vector& data) const { if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h index 76d0e9ae4..3d1cb4609 100644 --- a/src/core/hle/service/nfp/nfp_device.h +++ b/src/core/hle/service/nfp/nfp_device.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include "common/common_funcs.h" @@ -37,7 +38,7 @@ public: void Initialize(); void Finalize(); - Result StartDetection(s32 protocol_); + Result StartDetection(TagProtocol allowed_protocol); Result StopDetection(); Result Mount(MountTarget mount_target); Result Unmount(); @@ -53,6 +54,7 @@ public: Result DeleteAllData(); Result OpenApplicationArea(u32 access_id); + Result GetApplicationAreaId(u32& application_area_id) const; Result GetApplicationArea(std::vector& data) const; Result SetApplicationArea(std::span data); Result CreateApplicationArea(u32 access_id, std::span data); @@ -88,7 +90,7 @@ private: bool is_data_moddified{}; bool is_app_area_open{}; - s32 protocol{}; + TagProtocol allowed_protocols{}; s64 current_posix_time{}; MountTarget mount_target{MountTarget::None}; DeviceState device_state{DeviceState::Unavailable}; diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 63d5917cb..866aefe20 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -88,11 +88,15 @@ enum class PackedTagType : u8 { Type5, // ISO15693 RW/RO 540 bytes 106kbit/s }; +// Verify this enum. It might be completely wrong default protocol is 0x48 enum class TagProtocol : u32 { None, - TypeA, // ISO14443A - TypeB, // ISO14443B - TypeF, // Sony Felica + TypeA = 1U << 0, // ISO14443A + TypeB = 1U << 1, // ISO14443B + TypeF = 1U << 2, // Sony Felica + Unknown1 = 1U << 3, + Unknown2 = 1U << 5, + All = 0xFFFFFFFFU, }; using UniqueSerialNumber = std::array; diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp index 33e2ef518..ac492cc27 100644 --- a/src/core/hle/service/nfp/nfp_user.cpp +++ b/src/core/hle/service/nfp/nfp_user.cpp @@ -130,7 +130,7 @@ void IUser::ListDevices(Kernel::HLERequestContext& ctx) { void IUser::StartDetection(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto device_handle{rp.Pop()}; - const auto nfp_protocol{rp.Pop()}; + const auto nfp_protocol{rp.PopEnum()}; LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); if (state == State::NonInitialized) { -- cgit v1.2.3 From fb57cd26a1219a5c91d2cb4dec402528f8ba308e Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 13 Nov 2022 11:07:48 -0600 Subject: service: am: Implement cabinet applet backend --- src/core/hle/service/am/applets/applet_cabinet.cpp | 169 +++++++++++++++++++++ src/core/hle/service/am/applets/applet_cabinet.h | 99 ++++++++++++ src/core/hle/service/am/applets/applets.cpp | 20 ++- src/core/hle/service/am/applets/applets.h | 12 +- src/core/hle/service/nfp/nfp_types.h | 7 + 5 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 src/core/hle/service/am/applets/applet_cabinet.cpp create mode 100644 src/core/hle/service/am/applets/applet_cabinet.h (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp new file mode 100644 index 000000000..1eb5a9f22 --- /dev/null +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -0,0 +1,169 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "common/logging/log.h" +#include "core/core.h" +#include "core/frontend/applets/cabinet.h" +#include "core/hid/hid_core.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applets/applet_cabinet.h" +#include "core/hle/service/mii/mii_manager.h" +#include "core/hle/service/nfp/nfp_device.h" + +namespace Service::AM::Applets { + +Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, + const Core::Frontend::CabinetApplet& frontend_) + : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, service_context{ + system_, + "CabinetApplet"} { + + availability_change_event = + service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent"); +} + +Cabinet::~Cabinet() = default; + +void Cabinet::Initialize() { + Applet::Initialize(); + + LOG_INFO(Service_HID, "Initializing Cabinet Applet."); + + LOG_ERROR(Service_HID, + "Initializing Applet with common_args: arg_version={}, lib_version={}, " + "play_startup_sound={}, size={}, system_tick={}, theme_color={}", + common_args.arguments_version, common_args.library_version, + common_args.play_startup_sound, common_args.size, common_args.system_tick, + common_args.theme_color); + + const auto storage = broker.PopNormalDataToApplet(); + ASSERT(storage != nullptr); + + const auto applet_input_data = storage->GetData(); + ASSERT(applet_input_data.size() >= sizeof(StartParamForAmiiboSettings)); + + std::memcpy(&applet_input_common, applet_input_data.data(), + sizeof(StartParamForAmiiboSettings)); +} + +bool Cabinet::TransactionComplete() const { + return is_complete; +} + +Result Cabinet::GetStatus() const { + return ResultSuccess; +} + +void Cabinet::ExecuteInteractive() { + ASSERT_MSG(false, "Attempted to call interactive execution on non-interactive applet."); +} + +void Cabinet::Execute() { + if (is_complete) { + return; + } + + const auto callback = [this](bool apply_changes, const std::string& amiibo_name) { + DisplayCompleted(apply_changes, amiibo_name); + }; + + // TODO: listen on all controllers + if (nfp_device == nullptr) { + nfp_device = std::make_shared( + system.HIDCore().GetFirstNpadId(), system, service_context, availability_change_event); + nfp_device->Initialize(); + nfp_device->StartDetection(Service::NFP::TagProtocol::All); + } + + const Core::Frontend::CabinetParameters parameters{ + .tag_info = applet_input_common.tag_info, + .register_info = applet_input_common.register_info, + .mode = applet_input_common.applet_mode, + }; + + switch (applet_input_common.applet_mode) { + case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: + case Service::NFP::CabinetMode::StartGameDataEraser: + case Service::NFP::CabinetMode::StartRestorer: + case Service::NFP::CabinetMode::StartFormatter: + frontend.ShowCabinetApplet(callback, parameters, nfp_device); + break; + default: + UNIMPLEMENTED_MSG("Unknown CabinetMode={}", applet_input_common.applet_mode); + DisplayCompleted(false, {}); + break; + } +} + +void Cabinet::DisplayCompleted(bool apply_changes, const std::string& amiibo_name) { + Service::Mii::MiiManager manager; + ReturnValueForAmiiboSettings applet_output{}; + + if (!apply_changes) { + Cancel(); + } + + if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && + nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { + Cancel(); + } + + if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound) { + nfp_device->Mount(Service::NFP::MountTarget::All); + } + + switch (applet_input_common.applet_mode) { + case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: { + Service::NFP::AmiiboName name{}; + memccpy(name.data(), amiibo_name.data(), 0, name.size()); + nfp_device->SetNicknameAndOwner(name); + break; + } + case Service::NFP::CabinetMode::StartGameDataEraser: + nfp_device->DeleteApplicationArea(); + break; + case Service::NFP::CabinetMode::StartRestorer: + nfp_device->RestoreAmiibo(); + break; + case Service::NFP::CabinetMode::StartFormatter: + nfp_device->DeleteAllData(); + break; + default: + UNIMPLEMENTED_MSG("Unknown CabinetMode={}", applet_input_common.applet_mode); + break; + } + + applet_output.device_handle = applet_input_common.device_handle; + applet_output.result = CabinetResult::Success; + nfp_device->GetRegisterInfo(applet_output.register_info); + nfp_device->GetTagInfo(applet_output.tag_info); + nfp_device->Finalize(); + + std::vector out_data(sizeof(ReturnValueForAmiiboSettings)); + std::memcpy(out_data.data(), &applet_output, sizeof(ReturnValueForAmiiboSettings)); + + is_complete = true; + + broker.PushNormalDataFromApplet(std::make_shared(system, std::move(out_data))); + broker.SignalStateChanged(); +} + +void Cabinet::Cancel() { + ReturnValueForAmiiboSettings applet_output{}; + applet_output.device_handle = applet_input_common.device_handle; + applet_output.result = CabinetResult::Cancel; + nfp_device->Finalize(); + + std::vector out_data(sizeof(ReturnValueForAmiiboSettings)); + std::memcpy(out_data.data(), &applet_output, sizeof(ReturnValueForAmiiboSettings)); + + is_complete = true; + + broker.PushNormalDataFromApplet(std::make_shared(system, std::move(out_data))); + broker.SignalStateChanged(); +} + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h new file mode 100644 index 000000000..2d3f22434 --- /dev/null +++ b/src/core/hle/service/am/applets/applet_cabinet.h @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "core/hle/result.h" +#include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nfp/nfp_types.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Core { +class System; +} // namespace Core + +namespace Service::NFP { +class NfpDevice; +} + +namespace Service::AM::Applets { + +enum class CabinetAppletVersion : s32 { + Version1 = 0x1, +}; + +enum class CabinetResult : u8 { + Cancel, + Success, +}; + +// This is nn::nfp::AmiiboSettingsStartParam +struct AmiiboSettingsStartParam { + u64 device_handle; + std::array param_1; + std::array param_2; +}; +static_assert(sizeof(AmiiboSettingsStartParam) == 0x30, + "AmiiboSettingsStartParam is an invalid size"); + +// This is nn::nfp::StartParamForAmiiboSettings +struct StartParamForAmiiboSettings { + u8 param_1; + Service::NFP::CabinetMode applet_mode; + u8 flags; + u8 amiibo_settings_1; + u64 device_handle; + Service::NFP::TagInfo tag_info; + Service::NFP::RegisterInfo register_info; + std::array amiibo_settings_3; + INSERT_PADDING_BYTES(0x20); +}; +static_assert(sizeof(StartParamForAmiiboSettings) == 0x1A8, + "StartParamForAmiiboSettings is an invalid size"); + +// This is nn::nfp::ReturnValueForAmiiboSettings +struct ReturnValueForAmiiboSettings { + CabinetResult result; + INSERT_PADDING_BYTES(0x3); + u64 device_handle; + Service::NFP::TagInfo tag_info; + Service::NFP::RegisterInfo register_info; + INSERT_PADDING_BYTES(0x24); +}; +static_assert(sizeof(ReturnValueForAmiiboSettings) == 0x190, + "ReturnValueForAmiiboSettings is an invalid size"); + +class Cabinet final : public Applet { +public: + explicit Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, + const Core::Frontend::CabinetApplet& frontend_); + ~Cabinet() override; + + void Initialize() override; + + bool TransactionComplete() const override; + Result GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; + void DisplayCompleted(bool apply_changes, const std::string& amiibo_name); + void Cancel(); + +private: + const Core::Frontend::CabinetApplet& frontend; + Core::System& system; + + bool is_complete{false}; + std::shared_ptr nfp_device; + Kernel::KEvent* availability_change_event; + KernelHelpers::ServiceContext service_context; + StartParamForAmiiboSettings applet_input_common{}; +}; + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 7062df21c..10afbc2da 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -5,6 +5,7 @@ #include "common/assert.h" #include "core/core.h" +#include "core/frontend/applets/cabinet.h" #include "core/frontend/applets/controller.h" #include "core/frontend/applets/error.h" #include "core/frontend/applets/general_frontend.h" @@ -16,6 +17,7 @@ #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" +#include "core/hle/service/am/applets/applet_cabinet.h" #include "core/hle/service/am/applets/applet_controller.h" #include "core/hle/service/am/applets/applet_error.h" #include "core/hle/service/am/applets/applet_general_backend.h" @@ -171,13 +173,15 @@ void Applet::Initialize() { AppletFrontendSet::AppletFrontendSet() = default; -AppletFrontendSet::AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet, +AppletFrontendSet::AppletFrontendSet(CabinetApplet cabinet_applet, + ControllerApplet controller_applet, ErrorApplet error_applet, MiiEdit mii_edit_, ParentalControlsApplet parental_controls_applet, PhotoViewer photo_viewer_, ProfileSelect profile_select_, SoftwareKeyboard software_keyboard_, WebBrowser web_browser_) - : controller{std::move(controller_applet)}, error{std::move(error_applet)}, - mii_edit{std::move(mii_edit_)}, parental_controls{std::move(parental_controls_applet)}, + : cabinet{std::move(cabinet_applet)}, controller{std::move(controller_applet)}, + error{std::move(error_applet)}, mii_edit{std::move(mii_edit_)}, + parental_controls{std::move(parental_controls_applet)}, photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)}, software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {} @@ -196,6 +200,10 @@ const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const { } void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { + if (set.cabinet != nullptr) { + frontend.cabinet = std::move(set.cabinet); + } + if (set.controller != nullptr) { frontend.controller = std::move(set.controller); } @@ -235,6 +243,10 @@ void AppletManager::SetDefaultAppletFrontendSet() { } void AppletManager::SetDefaultAppletsIfMissing() { + if (frontend.cabinet == nullptr) { + frontend.cabinet = std::make_unique(); + } + if (frontend.controller == nullptr) { frontend.controller = std::make_unique(system.HIDCore()); @@ -279,6 +291,8 @@ std::shared_ptr AppletManager::GetApplet(AppletId id, LibraryAppletMode switch (id) { case AppletId::Auth: return std::make_shared(system, mode, *frontend.parental_controls); + case AppletId::Cabinet: + return std::make_shared(system, mode, *frontend.cabinet); case AppletId::Controller: return std::make_shared(system, mode, *frontend.controller); case AppletId::Error: diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 12c6a5b1a..a22eb62a8 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -16,6 +16,7 @@ class System; } namespace Core::Frontend { +class CabinetApplet; class ControllerApplet; class ECommerceApplet; class ErrorApplet; @@ -176,6 +177,7 @@ protected: }; struct AppletFrontendSet { + using CabinetApplet = std::unique_ptr; using ControllerApplet = std::unique_ptr; using ErrorApplet = std::unique_ptr; using MiiEdit = std::unique_ptr; @@ -186,10 +188,11 @@ struct AppletFrontendSet { using WebBrowser = std::unique_ptr; AppletFrontendSet(); - AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet, - MiiEdit mii_edit_, ParentalControlsApplet parental_controls_applet, - PhotoViewer photo_viewer_, ProfileSelect profile_select_, - SoftwareKeyboard software_keyboard_, WebBrowser web_browser_); + AppletFrontendSet(CabinetApplet cabinet_applet, ControllerApplet controller_applet, + ErrorApplet error_applet, MiiEdit mii_edit_, + ParentalControlsApplet parental_controls_applet, PhotoViewer photo_viewer_, + ProfileSelect profile_select_, SoftwareKeyboard software_keyboard_, + WebBrowser web_browser_); ~AppletFrontendSet(); AppletFrontendSet(const AppletFrontendSet&) = delete; @@ -198,6 +201,7 @@ struct AppletFrontendSet { AppletFrontendSet(AppletFrontendSet&&) noexcept; AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; + CabinetApplet cabinet; ControllerApplet controller; ErrorApplet error; MiiEdit mii_edit; diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 866aefe20..69858096a 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h @@ -99,6 +99,13 @@ enum class TagProtocol : u32 { All = 0xFFFFFFFFU, }; +enum class CabinetMode : u8 { + StartNicknameAndOwnerSettings, + StartGameDataEraser, + StartRestorer, + StartFormatter, +}; + using UniqueSerialNumber = std::array; using LockBytes = std::array; using HashData = std::array; -- cgit v1.2.3 From a253d1557d7d1fb1add6ae923ccb452d423d4547 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 13 Nov 2022 13:59:00 -0600 Subject: service: am: Fix cabinet applet result --- src/core/hle/service/am/applets/applet_cabinet.cpp | 20 ++++++++++++++------ src/core/hle/service/am/applets/applet_cabinet.h | 12 ++++++++---- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 1eb5a9f22..01f577ab9 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -32,7 +32,7 @@ void Cabinet::Initialize() { LOG_INFO(Service_HID, "Initializing Cabinet Applet."); - LOG_ERROR(Service_HID, + LOG_DEBUG(Service_HID, "Initializing Applet with common_args: arg_version={}, lib_version={}, " "play_startup_sound={}, size={}, system_tick={}, theme_color={}", common_args.arguments_version, common_args.library_version, @@ -111,14 +111,14 @@ void Cabinet::DisplayCompleted(bool apply_changes, const std::string& amiibo_nam Cancel(); } - if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound) { + if (nfp_device->GetCurrentState() == Service::NFP::DeviceState::TagFound) { nfp_device->Mount(Service::NFP::MountTarget::All); } switch (applet_input_common.applet_mode) { case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: { Service::NFP::AmiiboName name{}; - memccpy(name.data(), amiibo_name.data(), 0, name.size()); + memcpy(name.data(), amiibo_name.data(), std::min(amiibo_name.size(), name.size() - 1)); nfp_device->SetNicknameAndOwner(name); break; } @@ -137,11 +137,19 @@ void Cabinet::DisplayCompleted(bool apply_changes, const std::string& amiibo_nam } applet_output.device_handle = applet_input_common.device_handle; - applet_output.result = CabinetResult::Success; - nfp_device->GetRegisterInfo(applet_output.register_info); - nfp_device->GetTagInfo(applet_output.tag_info); + applet_output.result = CabinetResult::Cancel; + const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info); + const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info); nfp_device->Finalize(); + if (reg_result.IsSuccess() && tag_result.IsSuccess()) { + applet_output.result = CabinetResult::All; + } else if (reg_result.IsSuccess()) { + applet_output.result = CabinetResult::RegisterInfo; + } else if (tag_result.IsSuccess()) { + applet_output.result = CabinetResult::TagInfo; + } + std::vector out_data(sizeof(ReturnValueForAmiiboSettings)); std::memcpy(out_data.data(), &applet_output, sizeof(ReturnValueForAmiiboSettings)); diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h index 2d3f22434..8466d5997 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.h +++ b/src/core/hle/service/am/applets/applet_cabinet.h @@ -31,18 +31,21 @@ enum class CabinetAppletVersion : s32 { enum class CabinetResult : u8 { Cancel, - Success, + TagInfo = 1 << 1, + RegisterInfo = 1 << 2, + All = TagInfo | RegisterInfo, }; // This is nn::nfp::AmiiboSettingsStartParam struct AmiiboSettingsStartParam { u64 device_handle; std::array param_1; - std::array param_2; + u8 param_2; }; static_assert(sizeof(AmiiboSettingsStartParam) == 0x30, "AmiiboSettingsStartParam is an invalid size"); +#pragma pack(1) // This is nn::nfp::StartParamForAmiiboSettings struct StartParamForAmiiboSettings { u8 param_1; @@ -53,7 +56,7 @@ struct StartParamForAmiiboSettings { Service::NFP::TagInfo tag_info; Service::NFP::RegisterInfo register_info; std::array amiibo_settings_3; - INSERT_PADDING_BYTES(0x20); + INSERT_PADDING_BYTES(0x24); }; static_assert(sizeof(StartParamForAmiiboSettings) == 0x1A8, "StartParamForAmiiboSettings is an invalid size"); @@ -67,8 +70,9 @@ struct ReturnValueForAmiiboSettings { Service::NFP::RegisterInfo register_info; INSERT_PADDING_BYTES(0x24); }; -static_assert(sizeof(ReturnValueForAmiiboSettings) == 0x190, +static_assert(sizeof(ReturnValueForAmiiboSettings) == 0x188, "ReturnValueForAmiiboSettings is an invalid size"); +#pragma pack() class Cabinet final : public Applet { public: -- cgit v1.2.3 From 75e6ec85e107d6e5422d882b97faaa813970d42e Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 13 Nov 2022 15:14:08 -0600 Subject: general: Address review comments --- src/core/hle/service/am/applets/applet_cabinet.cpp | 16 ++++++++-------- src/core/hle/service/am/applets/applet_cabinet.h | 11 ++++++----- src/core/hle/service/nfp/nfp_device.cpp | 4 +++- 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 01f577ab9..d0969b0f1 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -98,7 +98,7 @@ void Cabinet::Execute() { } } -void Cabinet::DisplayCompleted(bool apply_changes, const std::string& amiibo_name) { +void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) { Service::Mii::MiiManager manager; ReturnValueForAmiiboSettings applet_output{}; @@ -118,7 +118,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, const std::string& amiibo_nam switch (applet_input_common.applet_mode) { case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: { Service::NFP::AmiiboName name{}; - memcpy(name.data(), amiibo_name.data(), std::min(amiibo_name.size(), name.size() - 1)); + std::memcpy(name.data(), amiibo_name.data(), std::min(amiibo_name.size(), name.size() - 1)); nfp_device->SetNicknameAndOwner(name); break; } @@ -142,12 +142,12 @@ void Cabinet::DisplayCompleted(bool apply_changes, const std::string& amiibo_nam const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info); nfp_device->Finalize(); - if (reg_result.IsSuccess() && tag_result.IsSuccess()) { - applet_output.result = CabinetResult::All; - } else if (reg_result.IsSuccess()) { - applet_output.result = CabinetResult::RegisterInfo; - } else if (tag_result.IsSuccess()) { - applet_output.result = CabinetResult::TagInfo; + if (reg_result.IsSuccess()) { + applet_output.result |= CabinetResult::RegisterInfo; + } + + if (tag_result.IsSuccess()) { + applet_output.result |= CabinetResult::TagInfo; } std::vector out_data(sizeof(ReturnValueForAmiiboSettings)); diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h index 8466d5997..84197a807 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.h +++ b/src/core/hle/service/am/applets/applet_cabinet.h @@ -25,16 +25,17 @@ class NfpDevice; namespace Service::AM::Applets { -enum class CabinetAppletVersion : s32 { +enum class CabinetAppletVersion : u32 { Version1 = 0x1, }; enum class CabinetResult : u8 { - Cancel, + Cancel = 0, TagInfo = 1 << 1, RegisterInfo = 1 << 2, All = TagInfo | RegisterInfo, }; +DECLARE_ENUM_FLAG_OPERATORS(CabinetResult) // This is nn::nfp::AmiiboSettingsStartParam struct AmiiboSettingsStartParam { @@ -45,7 +46,7 @@ struct AmiiboSettingsStartParam { static_assert(sizeof(AmiiboSettingsStartParam) == 0x30, "AmiiboSettingsStartParam is an invalid size"); -#pragma pack(1) +#pragma pack(push, 1) // This is nn::nfp::StartParamForAmiiboSettings struct StartParamForAmiiboSettings { u8 param_1; @@ -72,7 +73,7 @@ struct ReturnValueForAmiiboSettings { }; static_assert(sizeof(ReturnValueForAmiiboSettings) == 0x188, "ReturnValueForAmiiboSettings is an invalid size"); -#pragma pack() +#pragma pack(pop) class Cabinet final : public Applet { public: @@ -86,7 +87,7 @@ public: Result GetStatus() const override; void ExecuteInteractive() override; void Execute() override; - void DisplayCompleted(bool apply_changes, const std::string& amiibo_name); + void DisplayCompleted(bool apply_changes, std::string_view amiibo_name); void Cancel(); private: diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index 2f9dfa9c2..e1bf90d7c 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -148,7 +148,7 @@ void NfpDevice::Finalize() { device_state = DeviceState::Unavailable; } -Result NfpDevice::StartDetection([[maybe_unused]] TagProtocol allowed_protocol) { +Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); return WrongDeviceState; @@ -475,6 +475,8 @@ Result NfpDevice::OpenApplicationArea(u32 access_id) { } Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const { + application_area_id = {}; + if (device_state != DeviceState::TagMounted) { LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); if (device_state == DeviceState::TagRemoved) { -- cgit v1.2.3 From 6fa3faec658893c9fae19116232d24dac08babc7 Mon Sep 17 00:00:00 2001 From: Kyle Kienapfel Date: Fri, 11 Nov 2022 04:12:37 -0800 Subject: Add break for default cases Visual Studio has an option to search all files in a solution, so I did a search in there for "default:" looking for any missing break statements. I've left out default statements that return something, and that throw something, even if via ThrowInvalidType. UNREACHABLE leads towards throw R_THROW macro leads towards a return --- src/core/hle/service/am/applets/applet_error.cpp | 1 + src/core/hle/service/am/applets/applet_general_backend.cpp | 2 ++ src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 5 ++--- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 5 ++--- src/core/hle/service/service.cpp | 1 + src/core/hle/service/time/time_zone_manager.cpp | 1 + 6 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp index fcf34bf7e..bae0d99a6 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/applets/applet_error.cpp @@ -144,6 +144,7 @@ void Error::Initialize() { break; default: UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", mode); + break; } } diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp index c34ef08b3..e50acdaf6 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.cpp +++ b/src/core/hle/service/am/applets/applet_general_backend.cpp @@ -129,6 +129,7 @@ void Auth::Execute() { } default: unimplemented_log(); + break; } } @@ -192,6 +193,7 @@ void PhotoViewer::Execute() { break; default: UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", mode); + break; } } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index ced57dfe6..b97813fbc 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -300,11 +300,10 @@ Kernel::KEvent* nvhost_ctrl_gpu::QueryEvent(u32 event_id) { return error_notifier_event; case 2: return unknown_event; - default: { + default: LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); + return nullptr; } - } - return nullptr; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 45a759fa8..e123564c6 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -364,11 +364,10 @@ Kernel::KEvent* nvhost_gpu::QueryEvent(u32 event_id) { return sm_exception_breakpoint_pause_report_event; case 3: return error_notifier_event; - default: { + default: LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); + return nullptr; } - } - return nullptr; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5ab41c0c4..0de67f1e1 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -228,6 +228,7 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, } UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); + break; } // If emulation was shutdown, we are closing service threads, do not write the response back to diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp index 2aa675df9..f9ada7c93 100644 --- a/src/core/hle/service/time/time_zone_manager.cpp +++ b/src/core/hle/service/time/time_zone_manager.cpp @@ -280,6 +280,7 @@ static constexpr int TransitionTime(int year, Rule rule, int offset) { } default: ASSERT(false); + break; } return value + rule.transition_time + offset; } -- cgit v1.2.3 From cf202f371862ebe92dd88924a9f7b8cfbc7ad738 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 14 Nov 2022 21:00:32 -0500 Subject: nvnflinger: fix lost wakeup --- src/core/hle/service/nvflinger/buffer_queue_core.cpp | 6 ++++-- src/core/hle/service/nvflinger/buffer_queue_core.h | 5 +++-- src/core/hle/service/nvflinger/buffer_queue_producer.cpp | 14 +++++++------- src/core/hle/service/nvflinger/buffer_queue_producer.h | 3 ++- 4 files changed, 16 insertions(+), 12 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp index ea4a14ea4..3d1338e66 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_core.cpp @@ -23,15 +23,17 @@ void BufferQueueCore::NotifyShutdown() { } void BufferQueueCore::SignalDequeueCondition() { + dequeue_possible.store(true); dequeue_condition.notify_all(); } -bool BufferQueueCore::WaitForDequeueCondition() { +bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock& lk) { if (is_shutting_down) { return false; } - dequeue_condition.wait(mutex); + dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); + dequeue_possible.store(false); return true; } diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.h b/src/core/hle/service/nvflinger/buffer_queue_core.h index ca6baefaf..85b3bc4c1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvflinger/buffer_queue_core.h @@ -38,7 +38,7 @@ public: private: void SignalDequeueCondition(); - bool WaitForDequeueCondition(); + bool WaitForDequeueCondition(std::unique_lock& lk); s32 GetMinUndequeuedBufferCountLocked(bool async) const; s32 GetMinMaxBufferCountLocked(bool async) const; @@ -60,7 +60,8 @@ private: BufferQueueDefs::SlotsType slots{}; std::vector queue; s32 override_max_buffer_count{}; - mutable std::condition_variable_any dequeue_condition; + std::condition_variable dequeue_condition; + std::atomic dequeue_possible{}; const bool use_async_buffer{}; // This is always disabled on HOS bool dequeue_buffer_cannot_block{}; PixelFormat default_buffer_format{PixelFormat::Rgba8888}; diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp index 41ba44b21..e601b5da1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp @@ -121,8 +121,8 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { return Status::NoError; } -Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, - Status* return_flags) const { +Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, + std::unique_lock& lk) const { bool try_again = true; while (try_again) { @@ -214,7 +214,7 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, return Status::WouldBlock; } - if (!core->WaitForDequeueCondition()) { + if (!core->WaitForDequeueCondition(lk)) { // We are no longer running return Status::NoError; } @@ -237,7 +237,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool Status return_flags = Status::NoError; bool attached_by_consumer = false; { - std::scoped_lock lock{core->mutex}; + std::unique_lock lock{core->mutex}; core->WaitWhileAllocatingLocked(); if (format == PixelFormat::NoFormat) { @@ -248,7 +248,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool usage |= core->consumer_usage_bit; s32 found{}; - Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags); + Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags, lock); if (status != Status::NoError) { return status; } @@ -400,13 +400,13 @@ Status BufferQueueProducer::AttachBuffer(s32* out_slot, return Status::BadValue; } - std::scoped_lock lock{core->mutex}; + std::unique_lock lock{core->mutex}; core->WaitWhileAllocatingLocked(); Status return_flags = Status::NoError; s32 found{}; - const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags); + const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags, lock); if (status != Status::NoError) { return status; } diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h index 7526bf8ec..1d380480f 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.h @@ -70,7 +70,8 @@ public: private: BufferQueueProducer(const BufferQueueProducer&) = delete; - Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags) const; + Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, + std::unique_lock& lk) const; Kernel::KEvent* buffer_wait_event{}; Service::KernelHelpers::ServiceContext& service_context; -- cgit v1.2.3 From aa075a0c08335b1d145b2885eb0ba2f395b74f90 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 5 Nov 2022 11:40:19 -0600 Subject: service: hid: Only overclock npad controllers --- src/core/hle/service/hid/hid.cpp | 32 +++++++++++++++++++++++++++----- src/core/hle/service/hid/hid.h | 4 +++- 2 files changed, 30 insertions(+), 6 deletions(-) (limited to 'src/core/hle/service') diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 79375bd2f..bf28440c6 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -36,8 +36,9 @@ namespace Service::HID { // Updating period for each HID device. // Period time is obtained by measuring the number of samples in a second on HW using a homebrew -// Correct pad_update_ns is 4ms this is overclocked to lower input lag -constexpr auto pad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) +// Correct npad_update_ns is 4ms this is overclocked to lower input lag +constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) +constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz) constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) @@ -75,8 +76,16 @@ IAppletResource::IAppletResource(Core::System& system_, GetController(HidController::UniquePad).SetCommonHeaderOffset(0x5A00); // Register update callbacks - pad_update_event = Core::Timing::CreateEvent( + npad_update_event = Core::Timing::CreateEvent( "HID::UpdatePadCallback", + [this](std::uintptr_t user_data, s64 time, + std::chrono::nanoseconds ns_late) -> std::optional { + const auto guard = LockService(); + UpdateNpad(user_data, ns_late); + return std::nullopt; + }); + default_update_event = Core::Timing::CreateEvent( + "HID::UpdateDefaultCallback", [this](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late) -> std::optional { const auto guard = LockService(); @@ -100,7 +109,9 @@ IAppletResource::IAppletResource(Core::System& system_, return std::nullopt; }); - system.CoreTiming().ScheduleLoopingEvent(pad_update_ns, pad_update_ns, pad_update_event); + system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event); + system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns, + default_update_event); system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns, mouse_keyboard_update_event); system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns, @@ -118,7 +129,8 @@ void IAppletResource::DeactivateController(HidController controller) { } IAppletResource::~IAppletResource() { - system.CoreTiming().UnscheduleEvent(pad_update_event, 0); + system.CoreTiming().UnscheduleEvent(npad_update_event, 0); + system.CoreTiming().UnscheduleEvent(default_update_event, 0); system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0); system.CoreTiming().UnscheduleEvent(motion_update_event, 0); } @@ -144,10 +156,20 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, if (controller == controllers[static_cast(HidController::Mouse)]) { continue; } + // Npad has it's own update event + if (controller == controllers[static_cast(HidController::NPad)]) { + continue; + } controller->OnUpdate(core_timing); } } +void IAppletResource::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + + controllers[static_cast(HidController::NPad)]->OnUpdate(core_timing); +} + void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 340d26fdc..b7c2a23ef 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -71,12 +71,14 @@ private: void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); + void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); KernelHelpers::ServiceContext& service_context; - std::shared_ptr pad_update_event; + std::shared_ptr npad_update_event; + std::shared_ptr default_update_event; std::shared_ptr mouse_keyboard_update_event; std::shared_ptr motion_update_event; -- cgit v1.2.3