Merge pull request #11632 from german77/hle_cabinet

service: am: Add support for LLE Cabinet Applet
This commit is contained in:
liamwhite 2023-10-01 19:24:46 -04:00 committed by GitHub
commit 99e2568304
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 985 additions and 60 deletions

View file

@ -8,6 +8,7 @@
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
@ -19,6 +20,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_mii_edit_types.h"
#include "core/hle/service/am/applets/applet_profile_select.h"
#include "core/hle/service/am/applets/applet_web_browser.h"
@ -33,11 +35,13 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
#include "core/hle/service/nvnflinger/nvnflinger.h"
#include "core/hle/service/pm/pm.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/vi/vi.h"
#include "core/hle/service/vi/vi_results.h"
#include "core/memory.h"
namespace Service::AM {
@ -190,7 +194,7 @@ IDisplayController::IDisplayController(Core::System& system_)
{4, nullptr, "UpdateCallerAppletCaptureImage"},
{5, nullptr, "GetLastForegroundCaptureImageEx"},
{6, nullptr, "GetLastApplicationCaptureImageEx"},
{7, nullptr, "GetCallerAppletCaptureImageEx"},
{7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
{8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
{9, nullptr, "CopyBetweenCaptureBuffers"},
{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
@ -208,8 +212,8 @@ IDisplayController::IDisplayController(Core::System& system_)
{23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
{24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"},
{25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"},
{26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"},
{27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"},
{26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
{27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
{28, nullptr, "TakeScreenShotOfOwnLayerEx"},
};
// clang-format on
@ -219,6 +223,15 @@ IDisplayController::IDisplayController(Core::System& system_)
IDisplayController::~IDisplayController() = default;
void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(1u);
rb.Push(0);
}
void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
@ -226,6 +239,22 @@ void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(1U);
rb.Push(0);
}
void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
IDebugFunctions::IDebugFunctions(Core::System& system_)
: ServiceFramework{system_, "IDebugFunctions"} {
// clang-format off
@ -285,14 +314,14 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger&
{20, nullptr, "SetDesirableKeyboardLayout"},
{21, nullptr, "GetScreenShotProgramId"},
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{43, nullptr, "GetSystemSharedBufferHandle"},
{41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
{42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
{43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
{44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
{46, nullptr, "SetRecordingLayerCompositionEnabled"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
{51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
{61, nullptr, "SetMediaPlaybackState"},
{62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
@ -491,6 +520,50 @@ void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
rb.Push(*layer_id);
}
void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(this->EnsureBufferSharingEnabled());
}
void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(this->EnsureBufferSharingEnabled());
rb.Push<s64>(system_shared_buffer_id);
rb.Push<s64>(system_shared_layer_id);
}
void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(this->EnsureBufferSharingEnabled());
rb.Push<s64>(system_shared_buffer_id);
}
Result ISelfController::EnsureBufferSharingEnabled() {
if (buffer_sharing_enabled) {
return ResultSuccess;
}
if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) {
return VI::ResultOperationFailed;
}
const auto display_id = nvnflinger.OpenDisplay("Default");
const auto result = nvnflinger.GetSystemBufferManager().Initialize(
&system_shared_buffer_id, &system_shared_layer_id, *display_id);
if (result.IsSuccess()) {
buffer_sharing_enabled = true;
}
return result;
}
void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
@ -516,6 +589,13 @@ void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
idle_time_detection_extension = rp.Pop<u32>();
@ -686,7 +766,8 @@ void AppletMessageQueue::OperationModeChanged() {
ICommonStateGetter::ICommonStateGetter(Core::System& system_,
std::shared_ptr<AppletMessageQueue> msg_queue_)
: ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)} {
: ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
service_context{system_, "ICommonStateGetter"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
@ -699,10 +780,10 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
{7, nullptr, "GetCradleStatus"},
{8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
{9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
{10, nullptr, "RequestToAcquireSleepLock"},
{10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
{11, nullptr, "ReleaseSleepLock"},
{12, nullptr, "ReleaseSleepLockTransiently"},
{13, nullptr, "GetAcquiredSleepLockEvent"},
{13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
{14, nullptr, "GetWakeupCount"},
{20, nullptr, "PushToGeneralChannel"},
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
@ -745,6 +826,8 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
RegisterHandlers(functions);
sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
// Configure applets to be in foreground state
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
@ -793,6 +876,24 @@ void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
rb.Push(static_cast<u8>(FocusState::InFocus));
}
void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
// Sleep lock is acquired immediately.
sleep_lock_event->Signal();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
}
void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
@ -1385,7 +1486,16 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
// clang-format on
RegisterHandlers(functions);
PushInShowMiiEditData();
switch (system.GetAppletManager().GetCurrentAppletId()) {
case Applets::AppletId::Cabinet:
PushInShowCabinetData();
break;
case Applets::AppletId::MiiEdit:
PushInShowMiiEditData();
break;
default:
break;
}
}
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
@ -1431,7 +1541,7 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
const LibraryAppletInfo applet_info{
.applet_id = Applets::AppletId::MiiEdit,
.applet_id = system.GetAppletManager().GetCurrentAppletId(),
.library_applet_mode = Applets::LibraryAppletMode::AllForeground,
};
@ -1459,6 +1569,35 @@ void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext&
rb.PushRaw(applet_info);
}
void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
const Applets::CommonArguments arguments{
.arguments_version = Applets::CommonArgumentVersion::Version3,
.size = Applets::CommonArgumentSize::Version3,
.library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
.theme_color = Applets::ThemeColor::BasicBlack,
.play_startup_sound = true,
.system_tick = system.CoreTiming().GetClockTicks(),
};
const Applets::StartParamForAmiiboSettings amiibo_settings{
.param_1 = 0,
.applet_mode = system.GetAppletManager().GetCabinetMode(),
.flags = Applets::CabinetFlags::None,
.amiibo_settings_1 = 0,
.device_handle = 0,
.tag_info{},
.register_info{},
.amiibo_settings_3{},
};
std::vector<u8> argument_data(sizeof(arguments));
std::vector<u8> settings_data(sizeof(amiibo_settings));
std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
queue_data.emplace_back(std::move(argument_data));
queue_data.emplace_back(std::move(settings_data));
}
void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
struct MiiEditV3 {
Applets::MiiEditAppletInputCommon common;
@ -2235,7 +2374,7 @@ void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
}
void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
const auto applet_id = Applets::AppletId::MiiEdit;
const auto applet_id = system.GetAppletManager().GetCurrentAppletId();
const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
@ -2256,4 +2395,5 @@ void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx)
rb.Push(ResultSuccess);
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
}
} // namespace Service::AM

View file

@ -122,7 +122,10 @@ public:
~IDisplayController() override;
private:
void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
};
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
@ -150,9 +153,13 @@ private:
void SetRestartMessageEnabled(HLERequestContext& ctx);
void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
void SetAlbumImageOrientation(HLERequestContext& ctx);
void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
void GetSystemSharedBufferHandle(HLERequestContext& ctx);
void GetSystemSharedLayerHandle(HLERequestContext& ctx);
void CreateManagedDisplayLayer(HLERequestContext& ctx);
void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
void SetHandlesRequestToDisplay(HLERequestContext& ctx);
void ApproveToDisplay(HLERequestContext& ctx);
void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
void ReportUserIsActive(HLERequestContext& ctx);
@ -164,6 +171,8 @@ private:
void SaveCurrentScreenshot(HLERequestContext& ctx);
void SetRecordVolumeMuted(HLERequestContext& ctx);
Result EnsureBufferSharingEnabled();
enum class ScreenshotPermission : u32 {
Inherit = 0,
Enable = 1,
@ -179,7 +188,10 @@ private:
u32 idle_time_detection_extension = 0;
u64 num_fatal_sections_entered = 0;
u64 system_shared_buffer_id = 0;
u64 system_shared_layer_id = 0;
bool is_auto_sleep_disabled = false;
bool buffer_sharing_enabled = false;
ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
};
@ -223,6 +235,8 @@ private:
void GetEventHandle(HLERequestContext& ctx);
void ReceiveMessage(HLERequestContext& ctx);
void GetCurrentFocusState(HLERequestContext& ctx);
void RequestToAcquireSleepLock(HLERequestContext& ctx);
void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
void GetOperationMode(HLERequestContext& ctx);
void GetPerformanceMode(HLERequestContext& ctx);
@ -240,6 +254,8 @@ private:
std::shared_ptr<AppletMessageQueue> msg_queue;
bool vr_mode_state{};
Kernel::KEvent* sleep_lock_event;
KernelHelpers::ServiceContext service_context;
};
class IStorageImpl {
@ -311,6 +327,7 @@ private:
void ExitProcessAndReturn(HLERequestContext& ctx);
void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
void PushInShowCabinetData();
void PushInShowMiiEditData();
std::deque<std::vector<u8>> queue_data;

View file

@ -29,6 +29,15 @@ enum class CabinetAppletVersion : u32 {
Version1 = 0x1,
};
enum class CabinetFlags : u8 {
None = 0,
DeviceHandle = 1 << 0,
TagInfo = 1 << 1,
RegisterInfo = 1 << 2,
All = DeviceHandle | TagInfo | RegisterInfo,
};
DECLARE_ENUM_FLAG_OPERATORS(CabinetFlags)
enum class CabinetResult : u8 {
Cancel = 0,
TagInfo = 1 << 1,
@ -51,7 +60,7 @@ static_assert(sizeof(AmiiboSettingsStartParam) == 0x30,
struct StartParamForAmiiboSettings {
u8 param_1;
Service::NFP::CabinetMode applet_mode;
u8 flags;
CabinetFlags flags;
u8 amiibo_settings_1;
u64 device_handle;
Service::NFP::TagInfo tag_info;

View file

@ -223,9 +223,9 @@ void StubApplet::Initialize() {
const auto data = broker.PeekDataToAppletForDebug();
system.GetReporter().SaveUnimplementedAppletReport(
static_cast<u32>(id), common_args.arguments_version, common_args.library_version,
common_args.theme_color, common_args.play_startup_sound, common_args.system_tick,
data.normal, data.interactive);
static_cast<u32>(id), static_cast<u32>(common_args.arguments_version),
common_args.library_version, static_cast<u32>(common_args.theme_color),
common_args.play_startup_sound, common_args.system_tick, data.normal, data.interactive);
LogCurrentStorage(broker, "Initialize");
}

View file

@ -199,6 +199,14 @@ const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const {
return frontend;
}
NFP::CabinetMode AppletManager::GetCabinetMode() const {
return cabinet_mode;
}
AppletId AppletManager::GetCurrentAppletId() const {
return current_applet_id;
}
void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
if (set.cabinet != nullptr) {
frontend.cabinet = std::move(set.cabinet);
@ -237,6 +245,14 @@ void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
}
}
void AppletManager::SetCabinetMode(NFP::CabinetMode mode) {
cabinet_mode = mode;
}
void AppletManager::SetCurrentAppletId(AppletId applet_id) {
current_applet_id = applet_id;
}
void AppletManager::SetDefaultAppletFrontendSet() {
ClearAll();
SetDefaultAppletsIfMissing();

View file

@ -34,6 +34,10 @@ class KEvent;
class KReadableEvent;
} // namespace Kernel
namespace Service::NFP {
enum class CabinetMode : u8;
} // namespace Service::NFP
namespace Service::AM {
class IStorage;
@ -41,6 +45,8 @@ class IStorage;
namespace Applets {
enum class AppletId : u32 {
None = 0x00,
Application = 0x01,
OverlayDisplay = 0x02,
QLaunch = 0x03,
Starter = 0x04,
@ -71,6 +77,32 @@ enum class LibraryAppletMode : u32 {
AllForegroundInitiallyHidden = 4,
};
enum class CommonArgumentVersion : u32 {
Version0,
Version1,
Version2,
Version3,
};
enum class CommonArgumentSize : u32 {
Version3 = 0x20,
};
enum class ThemeColor : u32 {
BasicWhite = 0,
BasicBlack = 3,
};
struct CommonArguments {
CommonArgumentVersion arguments_version;
CommonArgumentSize size;
u32 library_version;
ThemeColor theme_color;
bool play_startup_sound;
u64_le system_tick;
};
static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
class AppletDataBroker final {
public:
explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_);
@ -161,16 +193,6 @@ public:
}
protected:
struct CommonArguments {
u32_le arguments_version;
u32_le size;
u32_le library_version;
u32_le theme_color;
bool play_startup_sound;
u64_le system_tick;
};
static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
CommonArguments common_args{};
AppletDataBroker broker;
LibraryAppletMode applet_mode;
@ -219,8 +241,12 @@ public:
~AppletManager();
const AppletFrontendSet& GetAppletFrontendSet() const;
NFP::CabinetMode GetCabinetMode() const;
AppletId GetCurrentAppletId() const;
void SetAppletFrontendSet(AppletFrontendSet set);
void SetCabinetMode(NFP::CabinetMode mode);
void SetCurrentAppletId(AppletId applet_id);
void SetDefaultAppletFrontendSet();
void SetDefaultAppletsIfMissing();
void ClearAll();
@ -228,6 +254,9 @@ public:
std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const;
private:
AppletId current_applet_id{};
NFP::CabinetMode cabinet_mode{};
AppletFrontendSet frontend;
Core::System& system;
};