Merge branch 'master' into nfc_impl
This commit is contained in:
commit
db7bcd51ae
91 changed files with 2270 additions and 246 deletions
177
src/core/hle/service/am/applets/applet_cabinet.cpp
Normal file
177
src/core/hle/service/am/applets/applet_cabinet.cpp
Normal file
|
@ -0,0 +1,177 @@
|
|||
// 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_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,
|
||||
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<Service::NFP::NfpDevice>(
|
||||
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, std::string_view 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{};
|
||||
std::memcpy(name.data(), amiibo_name.data(), std::min(amiibo_name.size(), name.size() - 1));
|
||||
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::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()) {
|
||||
applet_output.result |= CabinetResult::RegisterInfo;
|
||||
}
|
||||
|
||||
if (tag_result.IsSuccess()) {
|
||||
applet_output.result |= CabinetResult::TagInfo;
|
||||
}
|
||||
|
||||
std::vector<u8> out_data(sizeof(ReturnValueForAmiiboSettings));
|
||||
std::memcpy(out_data.data(), &applet_output, sizeof(ReturnValueForAmiiboSettings));
|
||||
|
||||
is_complete = true;
|
||||
|
||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(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<u8> out_data(sizeof(ReturnValueForAmiiboSettings));
|
||||
std::memcpy(out_data.data(), &applet_output, sizeof(ReturnValueForAmiiboSettings));
|
||||
|
||||
is_complete = true;
|
||||
|
||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||
broker.SignalStateChanged();
|
||||
}
|
||||
|
||||
} // namespace Service::AM::Applets
|
104
src/core/hle/service/am/applets/applet_cabinet.h
Normal file
104
src/core/hle/service/am/applets/applet_cabinet.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#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 : u32 {
|
||||
Version1 = 0x1,
|
||||
};
|
||||
|
||||
enum class CabinetResult : u8 {
|
||||
Cancel = 0,
|
||||
TagInfo = 1 << 1,
|
||||
RegisterInfo = 1 << 2,
|
||||
All = TagInfo | RegisterInfo,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(CabinetResult)
|
||||
|
||||
// This is nn::nfp::AmiiboSettingsStartParam
|
||||
struct AmiiboSettingsStartParam {
|
||||
u64 device_handle;
|
||||
std::array<u8, 0x20> param_1;
|
||||
u8 param_2;
|
||||
};
|
||||
static_assert(sizeof(AmiiboSettingsStartParam) == 0x30,
|
||||
"AmiiboSettingsStartParam is an invalid size");
|
||||
|
||||
#pragma pack(push, 1)
|
||||
// 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<u8, 0x20> amiibo_settings_3;
|
||||
INSERT_PADDING_BYTES(0x24);
|
||||
};
|
||||
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) == 0x188,
|
||||
"ReturnValueForAmiiboSettings is an invalid size");
|
||||
#pragma pack(pop)
|
||||
|
||||
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, std::string_view amiibo_name);
|
||||
void Cancel();
|
||||
|
||||
private:
|
||||
const Core::Frontend::CabinetApplet& frontend;
|
||||
Core::System& system;
|
||||
|
||||
bool is_complete{false};
|
||||
std::shared_ptr<Service::NFP::NfpDevice> nfp_device;
|
||||
Kernel::KEvent* availability_change_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
StartParamForAmiiboSettings applet_input_common{};
|
||||
};
|
||||
|
||||
} // namespace Service::AM::Applets
|
|
@ -144,6 +144,7 @@ void Error::Initialize() {
|
|||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Core::Frontend::DefaultCabinetApplet>();
|
||||
}
|
||||
|
||||
if (frontend.controller == nullptr) {
|
||||
frontend.controller =
|
||||
std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore());
|
||||
|
@ -279,6 +291,8 @@ std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode
|
|||
switch (id) {
|
||||
case AppletId::Auth:
|
||||
return std::make_shared<Auth>(system, mode, *frontend.parental_controls);
|
||||
case AppletId::Cabinet:
|
||||
return std::make_shared<Cabinet>(system, mode, *frontend.cabinet);
|
||||
case AppletId::Controller:
|
||||
return std::make_shared<Controller>(system, mode, *frontend.controller);
|
||||
case AppletId::Error:
|
||||
|
|
|
@ -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<Core::Frontend::CabinetApplet>;
|
||||
using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>;
|
||||
using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>;
|
||||
using MiiEdit = std::unique_ptr<Core::Frontend::MiiEditApplet>;
|
||||
|
@ -186,10 +188,11 @@ struct AppletFrontendSet {
|
|||
using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>;
|
||||
|
||||
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;
|
||||
|
|
|
@ -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<Controller_Stubbed>(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<std::chrono::nanoseconds> {
|
||||
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<std::chrono::nanoseconds> {
|
||||
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<size_t>(HidController::Mouse)]) {
|
||||
continue;
|
||||
}
|
||||
// Npad has it's own update event
|
||||
if (controller == controllers[static_cast<size_t>(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<size_t>(HidController::NPad)]->OnUpdate(core_timing);
|
||||
}
|
||||
|
||||
void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
|
||||
std::chrono::nanoseconds ns_late) {
|
||||
auto& core_timing = system.CoreTiming();
|
||||
|
|
|
@ -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<Core::Timing::EventType> pad_update_event;
|
||||
std::shared_ptr<Core::Timing::EventType> npad_update_event;
|
||||
std::shared_ptr<Core::Timing::EventType> default_update_event;
|
||||
std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
|
||||
std::shared_ptr<Core::Timing::EventType> motion_update_event;
|
||||
|
||||
|
|
|
@ -75,6 +75,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();
|
||||
}
|
||||
|
@ -95,6 +98,8 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: Filter by allowed_protocols here
|
||||
|
||||
memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File));
|
||||
|
||||
device_state = DeviceState::TagFound;
|
||||
|
@ -141,7 +146,7 @@ void NfpDevice::Finalize() {
|
|||
device_state = DeviceState::Unavailable;
|
||||
}
|
||||
|
||||
Result NfpDevice::StartDetection(s32 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;
|
||||
|
@ -153,7 +158,7 @@ Result NfpDevice::StartDetection(s32 protocol_) {
|
|||
}
|
||||
|
||||
device_state = DeviceState::SearchingForTag;
|
||||
protocol = protocol_;
|
||||
allowed_protocols = allowed_protocol;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
|
@ -467,6 +472,32 @@ Result NfpDevice::OpenApplicationArea(u32 access_id) {
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
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) {
|
||||
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<u8>& data) const {
|
||||
if (device_state != DeviceState::TagMounted) {
|
||||
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
@ -36,7 +37,7 @@ public:
|
|||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
Result StartDetection(s32 protocol_);
|
||||
Result StartDetection(TagProtocol allowed_protocol);
|
||||
Result StopDetection();
|
||||
Result Mount(MountTarget mount_target);
|
||||
Result Unmount();
|
||||
|
@ -52,6 +53,7 @@ public:
|
|||
Result DeleteAllData();
|
||||
|
||||
Result OpenApplicationArea(u32 access_id);
|
||||
Result GetApplicationAreaId(u32& application_area_id) const;
|
||||
Result GetApplicationArea(std::vector<u8>& data) const;
|
||||
Result SetApplicationArea(std::span<const u8> data);
|
||||
Result CreateApplicationArea(u32 access_id, std::span<const u8> data);
|
||||
|
@ -87,7 +89,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};
|
||||
|
|
|
@ -88,11 +88,22 @@ 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,
|
||||
};
|
||||
|
||||
enum class CabinetMode : u8 {
|
||||
StartNicknameAndOwnerSettings,
|
||||
StartGameDataEraser,
|
||||
StartRestorer,
|
||||
StartFormatter,
|
||||
};
|
||||
|
||||
using UniqueSerialNumber = std::array<u8, 7>;
|
||||
|
|
|
@ -131,7 +131,7 @@ void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
|
|||
void IUser::StartDetection(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto device_handle{rp.Pop<u64>()};
|
||||
const auto nfp_protocol{rp.Pop<s32>()};
|
||||
const auto nfp_protocol{rp.PopEnum<TagProtocol>()};
|
||||
LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol);
|
||||
|
||||
if (state == State::NonInitialized) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<std::mutex>& 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;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
private:
|
||||
void SignalDequeueCondition();
|
||||
bool WaitForDequeueCondition();
|
||||
bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk);
|
||||
|
||||
s32 GetMinUndequeuedBufferCountLocked(bool async) const;
|
||||
s32 GetMinMaxBufferCountLocked(bool async) const;
|
||||
|
@ -60,7 +60,8 @@ private:
|
|||
BufferQueueDefs::SlotsType slots{};
|
||||
std::vector<BufferItem> queue;
|
||||
s32 override_max_buffer_count{};
|
||||
mutable std::condition_variable_any dequeue_condition;
|
||||
std::condition_variable dequeue_condition;
|
||||
std::atomic<bool> dequeue_possible{};
|
||||
const bool use_async_buffer{}; // This is always disabled on HOS
|
||||
bool dequeue_buffer_cannot_block{};
|
||||
PixelFormat default_buffer_format{PixelFormat::Rgba8888};
|
||||
|
|
|
@ -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<std::mutex>& 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;
|
||||
}
|
||||
|
|
|
@ -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<std::mutex>& lk) const;
|
||||
|
||||
Kernel::KEvent* buffer_wait_event{};
|
||||
Service::KernelHelpers::ServiceContext& service_context;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -280,6 +280,7 @@ static constexpr int TransitionTime(int year, Rule rule, int offset) {
|
|||
}
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
}
|
||||
return value + rule.transition_time + offset;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue