Extend applet manager services for the library applet

This commit adds stubs for the library applet and adds support for
writing to an AM IStorage.
This commit is contained in:
Billy Laws 2020-07-07 15:58:38 +01:00 committed by ◱ PixelyIon
parent 30936ce6dc
commit 6e074d596c
10 changed files with 159 additions and 5 deletions

View File

@ -86,6 +86,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/services/am/controller/IWindowController.cpp
${source_DIR}/skyline/services/am/storage/IStorage.cpp
${source_DIR}/skyline/services/am/storage/IStorageAccessor.cpp
${source_DIR}/skyline/services/am/applet/ILibraryAppletAccessor.cpp
${source_DIR}/skyline/services/hid/IHidServer.cpp
${source_DIR}/skyline/services/hid/IAppletResource.cpp
${source_DIR}/skyline/services/timesrv/IStaticService.cpp

View File

@ -0,0 +1,45 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <kernel/types/KProcess.h>
#include <services/account/IAccountServiceForApplication.h>
#include <services/am/storage/IStorage.h>
#include "ILibraryAppletAccessor.h"
namespace skyline::service::am {
ILibraryAppletAccessor::ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager) : stateChangeEvent(std::make_shared<type::KEvent>(state)), BaseService(state, manager, Service::am_ILibraryAppletAccessor, "am:ILibraryAppletAccessor", {
{0x0, SFUNC(ILibraryAppletAccessor::GetAppletStateChangedEvent)},
{0xa, SFUNC(ILibraryAppletAccessor::Start)},
{0x1e, SFUNC(ILibraryAppletAccessor::GetResult)},
{0x64, SFUNC(ILibraryAppletAccessor::PushInData)},
{0x65, SFUNC(ILibraryAppletAccessor::PopOutData)},
}) {}
void ILibraryAppletAccessor::GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
stateChangeEvent->Signal();
KHandle handle = state.process->InsertItem(stateChangeEvent);
state.logger->Debug("Applet State Change Event Handle: 0x{:X}", handle);
response.copyHandles.push_back(handle);
}
void ILibraryAppletAccessor::Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void ILibraryAppletAccessor::GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void ILibraryAppletAccessor::PushInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void ILibraryAppletAccessor::PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
constexpr u32 LaunchParameterMagic = 0xc79497ca; //!< This is the magic of the application launch parameters
constexpr size_t LaunchParameterSize = 0x88; //!< This is the size of the launch parameter IStorage
auto storageService = std::make_shared<IStorage>(state, manager, LaunchParameterSize);
storageService->Push<u32>(LaunchParameterMagic);
storageService->Push<u32>(1);
storageService->Push(constant::DefaultUserId);
manager.RegisterService(storageService, session, response);
}
}

View File

@ -0,0 +1,46 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <kernel/types/KEvent.h>
#include <services/base_service.h>
#include <services/serviceman.h>
namespace skyline::service::am {
/**
* @brief ILibraryAppletAccessor is used to communicate with the library applet (https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletAccessor)
*/
class ILibraryAppletAccessor : public BaseService {
private:
std::shared_ptr<kernel::type::KEvent> stateChangeEvent; //!< This KEvent is triggered when the applet's state changes
public:
ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager);
/**
* @brief This function returns a handle to the library applet state change event
*/
void GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function starts the library applet (https://switchbrew.org/wiki/Applet_Manager_services#Start)
*/
void Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function returns the exit code of the library applet (https://switchbrew.org/wiki/Applet_Manager_services#GetResult)
*/
void GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function pushes in data to the library applet (https://switchbrew.org/wiki/Applet_Manager_services#PushInData)
*/
void PushInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function receives data from the library applet (https://switchbrew.org/wiki/Applet_Manager_services#PopOutData)
*/
void PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}

View File

@ -1,9 +1,26 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <services/am/storage/IStorage.h>
#include <services/am/applet/ILibraryAppletAccessor.h>
#include "ILibraryAppletCreator.h"
namespace skyline::service::am {
ILibraryAppletCreator::ILibraryAppletCreator(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::am_ILibraryAppletCreator, "am:ILibraryAppletCreator", {
{0x0, SFUNC(ILibraryAppletCreator::CreateLibraryApplet)},
{0xa, SFUNC(ILibraryAppletCreator::CreateStorage)}
}) {}
void ILibraryAppletCreator::CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.RegisterService(SRVREG(ILibraryAppletAccessor), session, response);
}
void ILibraryAppletCreator::CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto size = request.Pop<i64>();
if (size < 0)
throw exception("Cannot create an IStorage with a negative size");
manager.RegisterService(std::make_shared<IStorage>(state, manager, size), session, response);
}
}

View File

@ -13,5 +13,15 @@ namespace skyline::service::am {
class ILibraryAppletCreator : public BaseService {
public:
ILibraryAppletCreator(const DeviceState &state, ServiceManager &manager);
/**
* @brief This function returns a handle to a library applet accessor (https://switchbrew.org/wiki/Applet_Manager_services#CreateLibraryApplet)
*/
void CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function creates an IStorage that can be used by the application (https://switchbrew.org/wiki/Applet_Manager_services#CreateStorage)
*/
void CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}

View File

@ -7,7 +7,8 @@
#include "ISelfController.h"
namespace skyline::service::am {
ISelfController::ISelfController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::am_ISelfController, "am:ISelfController", {
ISelfController::ISelfController(const DeviceState &state, ServiceManager &manager) : libraryAppletLaunchableEvent(std::make_shared<type::KEvent>(state)), BaseService(state, manager, Service::am_ISelfController, "am:ISelfController", {
{0x9, SFUNC(ISelfController::GetLibraryAppletLaunchableEvent)},
{0xB, SFUNC(ISelfController::SetOperationModeChangedNotification)},
{0xC, SFUNC(ISelfController::SetPerformanceModeChangedNotification)},
{0xD, SFUNC(ISelfController::SetFocusHandlingMode)},
@ -15,6 +16,15 @@ namespace skyline::service::am {
{0x28, SFUNC(ISelfController::CreateManagedDisplayLayer)}
}) {}
void ISelfController::GetLibraryAppletLaunchableEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
libraryAppletLaunchableEvent->Signal();
KHandle handle = state.process->InsertItem(libraryAppletLaunchableEvent);
state.logger->Debug("Library Applet Launchable Event Handle: 0x{:X}", handle);
response.copyHandles.push_back(handle);
}
void ISelfController::SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void ISelfController::SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}

View File

@ -11,9 +11,17 @@ namespace skyline::service::am {
* @brief This has functions relating to an application's own current status (https://switchbrew.org/wiki/Applet_Manager_services#ISelfController)
*/
class ISelfController : public BaseService {
private:
std::shared_ptr<kernel::type::KEvent> libraryAppletLaunchableEvent; //!< This KEvent is triggered when the library applet is launchable
public:
ISelfController(const DeviceState &state, ServiceManager &manager);
/**
* @brief This function obtains a handle to the library applet launchable event (https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletLaunchableEvent)
*/
void GetLibraryAppletLaunchableEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This function takes a u8 bool flag and no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetOperationModeChangedNotification)
*/

View File

@ -8,6 +8,7 @@
namespace skyline::service::am {
IStorageAccessor::IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr<IStorage> parent) : parent(parent), BaseService(state, manager, Service::am_IStorageAccessor, "am:IStorageAccessor", {
{0x0, SFUNC(IStorageAccessor::GetSize)},
{0xa, SFUNC(IStorageAccessor::Write)},
{0xb, SFUNC(IStorageAccessor::Read)}
}) {}
@ -15,16 +16,26 @@ namespace skyline::service::am {
response.Push<i64>(parent->content.size());
}
void IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
void IStorageAccessor::Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto offset = request.Pop<i64>();
auto size = request.inputBuf.at(0).size;
if (offset + size > parent->content.size())
throw exception("Trying to write past the end of an IStorage");
if (offset < 0)
throw exception("Trying to write before the start of an IStorage");
state.process->ReadMemory(parent->content.data() + offset, request.inputBuf.at(0).address, size);
}
void IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto offset = request.Pop<u64>();
auto size = request.outputBuf.at(0).size;
if (offset + size > parent->content.size())
throw exception("Trying to read past the end of an IStorage");
if (offset < 0)
throw exception("Trying to read before the start of an IStorage");
state.process->WriteMemory(parent->content.data() + offset, request.outputBuf.at(0).address, size);
}
}

View File

@ -24,6 +24,11 @@ namespace skyline::service::am {
*/
void GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This writes a buffer to the storage at the specified offset
*/
void Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns a buffer containing the contents of the storage at the specified offset
*/

View File

@ -40,6 +40,7 @@ namespace skyline::service {
am_IAudioController,
am_IDisplayController,
am_ILibraryAppletCreator,
am_ILibraryAppletAccessor,
am_IDebugFunctions,
am_IAppletCommonFunctions,
am_IStorage,