mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 12:21:51 +01:00
Infrastructure for applets to be implemented
This removes a stub for an applet and implements several applet related service calls.
This commit is contained in:
parent
164d4852fa
commit
dec0571eee
@ -241,8 +241,12 @@ add_library(skyline SHARED
|
||||
${source_DIR}/skyline/services/am/controller/ISelfController.cpp
|
||||
${source_DIR}/skyline/services/am/controller/IWindowController.cpp
|
||||
${source_DIR}/skyline/services/am/storage/IStorage.cpp
|
||||
${source_DIR}/skyline/services/am/storage/VectorIStorage.cpp
|
||||
${source_DIR}/skyline/services/am/storage/TransferMemoryIStorage.cpp
|
||||
${source_DIR}/skyline/services/am/storage/IStorageAccessor.cpp
|
||||
${source_DIR}/skyline/services/am/applet/ILibraryAppletAccessor.cpp
|
||||
${source_DIR}/skyline/services/am/applet/IApplet.cpp
|
||||
${source_DIR}/skyline/applet/applet_creator.cpp
|
||||
${source_DIR}/skyline/services/codec/IHardwareOpusDecoder.cpp
|
||||
${source_DIR}/skyline/services/codec/IHardwareOpusDecoderManager.cpp
|
||||
${source_DIR}/skyline/services/hid/IHidServer.cpp
|
||||
|
18
app/src/main/cpp/skyline/applet/applet_creator.cpp
Normal file
18
app/src/main/cpp/skyline/applet/applet_creator.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "applet_creator.h"
|
||||
|
||||
namespace skyline::applet {
|
||||
std::shared_ptr<service::am::IApplet> CreateApplet(
|
||||
const DeviceState &state, service::ServiceManager &manager,
|
||||
applet::AppletId appletId, const std::shared_ptr<kernel::type::KEvent> &onAppletStateChanged,
|
||||
const std::shared_ptr<kernel::type::KEvent> &onNormalDataPushFromApplet,
|
||||
const std::shared_ptr<kernel::type::KEvent> &onInteractiveDataPushFromApplet,
|
||||
service::applet::LibraryAppletMode appletMode) {
|
||||
switch (appletId) {
|
||||
default:
|
||||
throw exception("Unimplemented Applet: 0x{:X} ({})", static_cast<u32>(appletId), ToString(appletId));
|
||||
}
|
||||
}
|
||||
}
|
81
app/src/main/cpp/skyline/applet/applet_creator.h
Normal file
81
app/src/main/cpp/skyline/applet/applet_creator.h
Normal file
@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <common/macros.h>
|
||||
#include <services/am/applet/IApplet.h>
|
||||
#include <services/applet/common_arguments.h>
|
||||
|
||||
namespace skyline::applet {
|
||||
#define APPLETS \
|
||||
APPLET_ENTRY(None, 0x000) \
|
||||
APPLET_ENTRY(Application, 0x001) \
|
||||
APPLET_ENTRY(OverlayApplet, 0x002) \
|
||||
APPLET_ENTRY(SystemAppletMenu, 0x003) \
|
||||
APPLET_ENTRY(SystemApplication, 0x004) \
|
||||
APPLET_ENTRY(LibraryAppletAuth, 0x00A) \
|
||||
APPLET_ENTRY(LibraryAppletCabinet, 0x00B) \
|
||||
APPLET_ENTRY(LibraryAppletController, 0x00C) \
|
||||
APPLET_ENTRY(LibraryAppletDataErase, 0x00D) \
|
||||
APPLET_ENTRY(LibraryAppletError, 0x00E) \
|
||||
APPLET_ENTRY(LibraryAppletNetConnect, 0x00F) \
|
||||
APPLET_ENTRY(LibraryAppletPlayerSelect, 0x010) \
|
||||
APPLET_ENTRY(LibraryAppletSwkbd, 0x011) \
|
||||
APPLET_ENTRY(LibraryAppletMiiEdit, 0x012) \
|
||||
APPLET_ENTRY(LibraryAppletWeb, 0x013) \
|
||||
APPLET_ENTRY(LibraryAppletShop, 0x014) \
|
||||
APPLET_ENTRY(LibraryAppletPhotoViewer, 0x015) \
|
||||
APPLET_ENTRY(LibraryAppletSet, 0x016) \
|
||||
APPLET_ENTRY(LibraryAppletOfflineWeb, 0x017) \
|
||||
APPLET_ENTRY(LibraryAppletLoginShare, 0x018) \
|
||||
APPLET_ENTRY(LibraryAppletWifiWebAuth, 0x019) \
|
||||
APPLET_ENTRY(LibraryAppletMyPage, 0x01A) \
|
||||
APPLET_ENTRY(LibraryAppletGift, 0x01B) \
|
||||
APPLET_ENTRY(LibraryAppletUserMigration, 0x01C) \
|
||||
APPLET_ENTRY(LibraryAppletPreomiaSys, 0x01D) \
|
||||
APPLET_ENTRY(LibraryAppletStory, 0x01E) \
|
||||
APPLET_ENTRY(LibraryAppletPreomiaUsr, 0x01F) \
|
||||
APPLET_ENTRY(LibraryAppletPreomiaUsrDummy, 0x020) \
|
||||
APPLET_ENTRY(LibraryAppletSample, 0x021) \
|
||||
APPLET_ENTRY(DevlopmentTool, 0x3E8) \
|
||||
APPLET_ENTRY(CombinationLA, 0x3F1) \
|
||||
APPLET_ENTRY(AeSystemApplet, 0x3F2) \
|
||||
APPLET_ENTRY(AeOverlayApplet, 0x3F3) \
|
||||
APPLET_ENTRY(AeStarter, 0x3F4) \
|
||||
APPLET_ENTRY(AeLibraryAppletAlone, 0x3F5) \
|
||||
APPLET_ENTRY(AeLibraryApplet1, 0x3F6) \
|
||||
APPLET_ENTRY(AeLibraryApplet2, 0x3F7) \
|
||||
APPLET_ENTRY(AeLibraryApplet3, 0x3F8) \
|
||||
APPLET_ENTRY(AeLibraryApplet4, 0x3F9) \
|
||||
APPLET_ENTRY(AppletISA, 0x3FA) \
|
||||
APPLET_ENTRY(AppletIOA, 0x3FB) \
|
||||
APPLET_ENTRY(AppletISTA, 0x3FC) \
|
||||
APPLET_ENTRY(AppletILA1, 0x3FD) \
|
||||
APPLET_ENTRY(AppletILA2, 0x3FE)
|
||||
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#AppletId
|
||||
*/
|
||||
enum class AppletId : u32 {
|
||||
#define APPLET_ENTRY(name, id) name = id,
|
||||
APPLETS
|
||||
#undef APPLET_ENTRY
|
||||
};
|
||||
|
||||
#define APPLET_ENTRY(name, id) ENUM_CASE(name);
|
||||
|
||||
ENUM_STRING(AppletId, APPLETS)
|
||||
|
||||
#undef APPLET_ENTRY
|
||||
|
||||
/**
|
||||
* @brief Creates an Applet of the appropiate class depending on the AppletId
|
||||
*/
|
||||
std::shared_ptr<service::am::IApplet> CreateApplet(
|
||||
const DeviceState &state, service::ServiceManager &manager,
|
||||
applet::AppletId appletId, const std::shared_ptr<kernel::type::KEvent> &onAppletStateChanged,
|
||||
const std::shared_ptr<kernel::type::KEvent> &onNormalDataPushFromApplet,
|
||||
const std::shared_ptr<kernel::type::KEvent> &onInteractiveDataPushFromApplet,
|
||||
service::applet::LibraryAppletMode appletMode);
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <common.h>
|
||||
#include "types/KSession.h"
|
||||
#include "types/KProcess.h"
|
||||
|
||||
namespace skyline {
|
||||
namespace constant {
|
||||
@ -231,6 +233,20 @@ namespace skyline {
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pops a Service object from the response as a domain or kernel handle
|
||||
*/
|
||||
template<typename ServiceType>
|
||||
std::shared_ptr<ServiceType> PopService(u32 id, type::KSession &session) {
|
||||
std::shared_ptr<service::BaseService> serviceObject;
|
||||
if (session.isDomain)
|
||||
serviceObject = session.domains.at(domainObjects.at(id));
|
||||
else
|
||||
serviceObject = session.state.process->GetHandle<kernel::type::KSession>(moveHandles.at(id))->serviceObject;
|
||||
|
||||
return std::static_pointer_cast<ServiceType>(serviceObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Skips an object to pop off the top
|
||||
*/
|
||||
|
43
app/src/main/cpp/skyline/services/am/applet/IApplet.cpp
Normal file
43
app/src/main/cpp/skyline/services/am/applet/IApplet.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "IApplet.h"
|
||||
|
||||
namespace skyline::service::am {
|
||||
|
||||
IApplet::IApplet(const DeviceState &state, ServiceManager &manager, std::shared_ptr<kernel::type::KEvent> onAppletStateChanged, std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet, std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet, applet::LibraryAppletMode appletMode)
|
||||
: BaseService(state, manager), onAppletStateChanged(std::move(onAppletStateChanged)),
|
||||
onNormalDataPushFromApplet(std::move(onNormalDataPushFromApplet)),
|
||||
onInteractiveDataPushFromApplet(std::move(onInteractiveDataPushFromApplet)) {}
|
||||
|
||||
IApplet::~IApplet() = default;
|
||||
|
||||
void IApplet::PushNormalDataAndSignal(const std::shared_ptr<IStorage> &data) {
|
||||
normalOutputData.emplace(data);
|
||||
onNormalDataPushFromApplet->Signal();
|
||||
}
|
||||
|
||||
void IApplet::PushInteractiveDataAndSignal(const std::shared_ptr<IStorage> &data) {
|
||||
interactiveOutputData.emplace(data);
|
||||
onInteractiveDataPushFromApplet->Signal();
|
||||
}
|
||||
|
||||
std::shared_ptr<IStorage> IApplet::PopNormalAndClear() {
|
||||
if (normalOutputData.empty())
|
||||
return {};
|
||||
std::shared_ptr<IStorage> data(normalOutputData.front());
|
||||
normalOutputData.pop();
|
||||
onNormalDataPushFromApplet->ResetSignal();
|
||||
return data;
|
||||
}
|
||||
|
||||
std::shared_ptr<IStorage> IApplet::PopInteractiveAndClear() {
|
||||
if (interactiveOutputData.empty())
|
||||
return {};
|
||||
std::shared_ptr<IStorage> data(interactiveOutputData.front());
|
||||
interactiveOutputData.pop();
|
||||
onInteractiveDataPushFromApplet->ResetSignal();
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
71
app/src/main/cpp/skyline/services/am/applet/IApplet.h
Normal file
71
app/src/main/cpp/skyline/services/am/applet/IApplet.h
Normal file
@ -0,0 +1,71 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <services/am/storage/IStorage.h>
|
||||
#include <kernel/types/KEvent.h>
|
||||
#include <services/applet/common_arguments.h>
|
||||
|
||||
|
||||
namespace skyline::service::am {
|
||||
/**
|
||||
* @brief The base class all Applets have to inherit from
|
||||
*/
|
||||
class IApplet : public BaseService {
|
||||
private:
|
||||
std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet;
|
||||
std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<kernel::type::KEvent> onAppletStateChanged;
|
||||
std::queue<std::shared_ptr<IStorage>> normalOutputData; //!< Stores data sent by the applet so the guest can read it when it needs to
|
||||
std::queue<std::shared_ptr<IStorage>> interactiveOutputData; //!< Stores interactive data sent by the applet so the guest can read it when it needs to
|
||||
|
||||
/**
|
||||
* @brief Utility to send data to the guest and trigger the onNormalDataPushFromApplet event
|
||||
*/
|
||||
void PushNormalDataAndSignal(const std::shared_ptr<IStorage> &data);
|
||||
|
||||
/**
|
||||
* @brief Utility to send data to the guest and trigger the onInteractiveDataPushFromApplet event
|
||||
*/
|
||||
void PushInteractiveDataAndSignal(const std::shared_ptr<IStorage> &data);
|
||||
|
||||
public:
|
||||
IApplet(const DeviceState &state, ServiceManager &manager, std::shared_ptr<kernel::type::KEvent> onAppletStateChanged, std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet, std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet, applet::LibraryAppletMode appletMode);
|
||||
|
||||
virtual ~IApplet();
|
||||
|
||||
/**
|
||||
* @brief Called when the applet is started
|
||||
*/
|
||||
virtual Result Start() = 0;
|
||||
|
||||
/**
|
||||
* @brief Called when the applet is stopped
|
||||
*/
|
||||
virtual Result GetResult() = 0;
|
||||
|
||||
/**
|
||||
* @brief Called when data is pushed to the applet by the guest through the normal queue
|
||||
*/
|
||||
virtual void PushNormalDataToApplet(std::shared_ptr<IStorage> data) = 0;
|
||||
|
||||
/**
|
||||
* @brief Called when data is pushed to the applet by the guest through the interactive queue
|
||||
*/
|
||||
virtual void PushInteractiveDataToApplet(std::shared_ptr<IStorage> data) = 0;
|
||||
|
||||
/**
|
||||
* @brief Used by ILibraryAppletAccessor to pop data from the normal queue and reset the corresponding event
|
||||
*/
|
||||
std::shared_ptr<IStorage> PopNormalAndClear();
|
||||
|
||||
/**
|
||||
* @brief Used by ILibraryAppletAccessor to pop data from the interactive queue and reset the corresponding event
|
||||
*/
|
||||
std::shared_ptr<IStorage> PopInteractiveAndClear();
|
||||
};
|
||||
}
|
@ -1,47 +1,73 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
// Copyright © 2020 Ryujinx Team and Contributors
|
||||
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include <services/account/IAccountServiceForApplication.h>
|
||||
#include <services/am/storage/IStorage.h>
|
||||
#include <services/am/storage/VectorIStorage.h>
|
||||
#include <applet/applet_creator.h>
|
||||
#include "ILibraryAppletAccessor.h"
|
||||
|
||||
namespace skyline::service::am {
|
||||
ILibraryAppletAccessor::ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager) : stateChangeEvent(std::make_shared<type::KEvent>(state, false)), BaseService(state, manager) {}
|
||||
ILibraryAppletAccessor::ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager, skyline::applet::AppletId appletId, applet::LibraryAppletMode appletMode)
|
||||
: BaseService(state, manager),
|
||||
stateChangeEvent(std::make_shared<type::KEvent>(state, false)),
|
||||
popNormalOutDataEvent((std::make_shared<type::KEvent>(state, false))),
|
||||
popInteractiveOutDataEvent((std::make_shared<type::KEvent>(state, false))),
|
||||
applet(skyline::applet::CreateApplet(state, manager, appletId, stateChangeEvent, popNormalOutDataEvent, popInteractiveOutDataEvent, appletMode)) {
|
||||
stateChangeEventHandle = state.process->InsertItem(stateChangeEvent);
|
||||
popNormalOutDataEventHandle = state.process->InsertItem(popNormalOutDataEvent);
|
||||
popInteractiveOutDataEventHandle = state.process->InsertItem(popInteractiveOutDataEvent);
|
||||
Logger::Debug("Applet accessor for {} ID created with appletMode 0x{:X}", ToString(appletId), appletMode);
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
stateChangeEvent->Signal();
|
||||
|
||||
KHandle handle{state.process->InsertItem(stateChangeEvent)};
|
||||
Logger::Debug("Applet State Change Event Handle: 0x{:X}", handle);
|
||||
|
||||
response.copyHandles.push_back(handle);
|
||||
Logger::Debug("Applet State Change Event Handle: 0x{:X}", stateChangeEventHandle);
|
||||
response.copyHandles.push_back(stateChangeEventHandle);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
return {};
|
||||
return applet->Start();
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
return {};
|
||||
return applet->GetResult();
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::PushInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
applet->PushNormalDataToApplet(request.PopService<IStorage>(0, session));
|
||||
return {};
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::PushInteractiveInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
applet->PushInteractiveDataToApplet(request.PopService<IStorage>(0, session));
|
||||
return {};
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< The magic of the application launch parameters
|
||||
constexpr size_t LaunchParameterSize{0x88}; //!< The size of the launch parameter IStorage
|
||||
if (auto outIStorage{applet->PopNormalAndClear()}) {
|
||||
manager.RegisterService(outIStorage, session, response);
|
||||
return {};
|
||||
}
|
||||
return result::NotAvailable;
|
||||
}
|
||||
|
||||
auto storageService{std::make_shared<IStorage>(state, manager, LaunchParameterSize)};
|
||||
Result ILibraryAppletAccessor::PopInteractiveOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
if (auto outIStorage = applet->PopInteractiveAndClear()) {
|
||||
manager.RegisterService(outIStorage, session, response);
|
||||
return {};
|
||||
}
|
||||
return result::NotAvailable;
|
||||
}
|
||||
|
||||
storageService->Push<u32>(LaunchParameterMagic);
|
||||
storageService->Push<u32>(1);
|
||||
storageService->Push(constant::DefaultUserId);
|
||||
Result ILibraryAppletAccessor::GetPopOutDataEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
response.copyHandles.push_back(popNormalOutDataEventHandle);
|
||||
return {};
|
||||
}
|
||||
|
||||
manager.RegisterService(storageService, session, response);
|
||||
Result ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
response.copyHandles.push_back(popInteractiveOutDataEventHandle);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
@ -5,21 +5,38 @@
|
||||
|
||||
#include <kernel/types/KEvent.h>
|
||||
#include <services/serviceman.h>
|
||||
#include "IApplet.h"
|
||||
#include <applet/applet_creator.h>
|
||||
|
||||
namespace skyline::service::am {
|
||||
namespace result {
|
||||
constexpr Result ObjectInvalid(128, 500);
|
||||
constexpr Result OutOfBounds(128, 503);
|
||||
constexpr Result NotAvailable(128, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ILibraryAppletAccessor is used to communicate with the library applet
|
||||
* @url 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
|
||||
std::shared_ptr<kernel::type::KEvent> stateChangeEvent;
|
||||
std::shared_ptr<kernel::type::KEvent> popNormalOutDataEvent;
|
||||
std::shared_ptr<kernel::type::KEvent> popInteractiveOutDataEvent;
|
||||
|
||||
KHandle stateChangeEventHandle{};
|
||||
KHandle popNormalOutDataEventHandle{};
|
||||
KHandle popInteractiveOutDataEventHandle{};
|
||||
|
||||
std::shared_ptr<IApplet> applet;
|
||||
|
||||
public:
|
||||
ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager);
|
||||
ILibraryAppletAccessor(const DeviceState &state, ServiceManager &manager, skyline::applet::AppletId appletId, applet::LibraryAppletMode appletMode);
|
||||
|
||||
/**
|
||||
* @brief Returns a handle to the library applet state change event
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetAppletStateChangedEvent
|
||||
*/
|
||||
Result GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
@ -47,12 +64,40 @@ namespace skyline::service::am {
|
||||
*/
|
||||
Result PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Pushes in data to the library applet, through the interactive queue
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#PushInteractiveInData
|
||||
*/
|
||||
Result PushInteractiveInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Receives data from the library applet, from the interactive queue
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#PopInteractiveOutData
|
||||
*/
|
||||
Result PopInteractiveOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Gets te KEvent for when there's data to be popped by the guest on the normal queue
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetPopOutDataEvent
|
||||
*/
|
||||
Result GetPopOutDataEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Gets the KEvent for when there's data to be popped by the guest on the interactive queue
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#GetPopInteractiveOutDataEvent
|
||||
*/
|
||||
Result GetPopInteractiveOutDataEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
SERVICE_DECL(
|
||||
SFUNC(0x0, ILibraryAppletAccessor, GetAppletStateChangedEvent),
|
||||
SFUNC(0xA, ILibraryAppletAccessor, Start),
|
||||
SFUNC(0x1E, ILibraryAppletAccessor, GetResult),
|
||||
SFUNC(0x64, ILibraryAppletAccessor, PushInData),
|
||||
SFUNC(0x65, ILibraryAppletAccessor, PopOutData)
|
||||
SFUNC(0x65, ILibraryAppletAccessor, PopOutData),
|
||||
SFUNC(0x67, ILibraryAppletAccessor, PushInteractiveInData),
|
||||
SFUNC(0x68, ILibraryAppletAccessor, PopInteractiveOutData),
|
||||
SFUNC(0x69, ILibraryAppletAccessor, GetPopOutDataEvent),
|
||||
SFUNC(0x6A, ILibraryAppletAccessor, GetPopInteractiveOutDataEvent)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <os.h>
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include <services/account/IAccountServiceForApplication.h>
|
||||
#include <services/am/storage/IStorage.h>
|
||||
#include <services/am/storage/VectorIStorage.h>
|
||||
#include "IApplicationFunctions.h"
|
||||
|
||||
namespace skyline::service::am {
|
||||
@ -29,7 +29,7 @@ namespace skyline::service::am {
|
||||
return result::NotAvailable;
|
||||
|
||||
case LaunchParameterKind::PreselectedUser: {
|
||||
storageService = std::make_shared<IStorage>(state, manager, LaunchParameterSize);
|
||||
storageService = std::make_shared<VectorIStorage>(state, manager, LaunchParameterSize);
|
||||
|
||||
storageService->Push<u32>(LaunchParameterMagic);
|
||||
storageService->Push<u32>(1);
|
||||
|
@ -1,25 +1,38 @@
|
||||
|
||||
// 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/storage/VectorIStorage.h>
|
||||
#include <services/am/storage/TransferMemoryIStorage.h>
|
||||
#include <services/am/applet/ILibraryAppletAccessor.h>
|
||||
#include <kernel/types/KTransferMemory.h>
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include "ILibraryAppletCreator.h"
|
||||
|
||||
namespace skyline::service::am {
|
||||
ILibraryAppletCreator::ILibraryAppletCreator(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {}
|
||||
|
||||
Result ILibraryAppletCreator::CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
manager.RegisterService(SRVREG(ILibraryAppletAccessor), session, response);
|
||||
auto appletId{request.Pop<skyline::applet::AppletId>()};
|
||||
auto appletMode{request.Pop<applet::LibraryAppletMode>()};
|
||||
manager.RegisterService(SRVREG(ILibraryAppletAccessor, appletId, appletMode), session, response);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result 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(SRVREG(VectorIStorage, size), session, response);
|
||||
return {};
|
||||
}
|
||||
|
||||
manager.RegisterService(std::make_shared<IStorage>(state, manager, size), session, response);
|
||||
Result ILibraryAppletCreator::CreateTransferMemoryStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
bool writable{request.Pop<u64>() != 0};
|
||||
i64 size{request.Pop<i64>()};
|
||||
if (size < 0)
|
||||
throw exception("Cannot create an IStorage with a negative size");
|
||||
manager.RegisterService(SRVREG(TransferMemoryIStorage, state.process->GetHandle<kernel::type::KTransferMemory>(request.copyHandles.at(0)), writable), session, response);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
@ -20,14 +20,21 @@ namespace skyline::service::am {
|
||||
Result CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Creates an IStorage that can be used by the application
|
||||
* @brief Creates an IStorage that can be used by the application, backed by service-allocated memory
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#CreateStorage
|
||||
*/
|
||||
Result CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Creates an IStorage that can be used by the application, backed by the supplied transfer memory
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#CreateTransferMemoryStorage
|
||||
*/
|
||||
Result CreateTransferMemoryStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
SERVICE_DECL(
|
||||
SFUNC(0x0, ILibraryAppletCreator, CreateLibraryApplet),
|
||||
SFUNC(0xA, ILibraryAppletCreator, CreateStorage)
|
||||
SFUNC(0xA, ILibraryAppletCreator, CreateStorage),
|
||||
SFUNC(0xB, ILibraryAppletCreator, CreateTransferMemoryStorage)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -5,10 +5,12 @@
|
||||
#include "IStorage.h"
|
||||
|
||||
namespace skyline::service::am {
|
||||
IStorage::IStorage(const DeviceState &state, ServiceManager &manager, size_t size) : content(size, 0), BaseService(state, manager) {}
|
||||
IStorage::IStorage(const DeviceState &state, ServiceManager &manager, bool writable) : writable(writable), BaseService(state, manager) {}
|
||||
|
||||
Result IStorage::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
manager.RegisterService(std::make_shared<IStorageAccessor>(state, manager, shared_from_this()), session, response);
|
||||
manager.RegisterService(std::make_shared<IStorageAccessor>(state, manager, std::static_pointer_cast<IStorage>(shared_from_this())), session, response);
|
||||
return {};
|
||||
}
|
||||
|
||||
IStorage::~IStorage() = default;
|
||||
}
|
||||
|
@ -10,14 +10,23 @@ namespace skyline::service::am {
|
||||
* @brief IStorage is used to open an IStorageAccessor to access a region of memory
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#IStorage
|
||||
*/
|
||||
class IStorage : public BaseService, public std::enable_shared_from_this<IStorage> {
|
||||
class IStorage : public BaseService {
|
||||
public:
|
||||
bool writable; //!< Whether the storage is writable by the guest
|
||||
private:
|
||||
size_t offset{}; //!< The current offset within the content for pushing data
|
||||
|
||||
public:
|
||||
std::vector<u8> content; //!< The container for this IStorage's contents
|
||||
protected:
|
||||
IStorage(const DeviceState &state, ServiceManager &manager, bool writable);
|
||||
|
||||
IStorage(const DeviceState &state, ServiceManager &manager, size_t size);
|
||||
public:
|
||||
|
||||
virtual ~IStorage();
|
||||
|
||||
/**
|
||||
* @brief A span of the backing storage for this IStorage
|
||||
*/
|
||||
virtual span <u8> GetSpan() = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns an IStorageAccessor that can read and write data to an IStorage
|
||||
@ -29,10 +38,10 @@ namespace skyline::service::am {
|
||||
*/
|
||||
template<typename ValueType>
|
||||
void Push(const ValueType &value) {
|
||||
if (offset + sizeof(ValueType) > content.size())
|
||||
if (offset + sizeof(ValueType) > this->GetSpan().size())
|
||||
throw exception("The supplied value cannot fit into the IStorage");
|
||||
|
||||
std::memcpy(content.data() + offset, reinterpret_cast<const u8 *>(&value), sizeof(ValueType));
|
||||
std::memcpy(this->GetSpan().data() + offset, reinterpret_cast<const u8 *>(&value), sizeof(ValueType));
|
||||
offset += sizeof(ValueType);
|
||||
}
|
||||
|
||||
|
@ -8,20 +8,23 @@ namespace skyline::service::am {
|
||||
IStorageAccessor::IStorageAccessor(const DeviceState &state, ServiceManager &manager, std::shared_ptr<IStorage> parent) : parent(std::move(parent)), BaseService(state, manager) {}
|
||||
|
||||
Result IStorageAccessor::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
response.Push<i64>(static_cast<i64>(parent->content.size()));
|
||||
response.Push<i64>(static_cast<i64>(parent->GetSpan().size()));
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IStorageAccessor::Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto offset{request.Pop<i64>()};
|
||||
|
||||
if (offset < 0 || offset > parent->content.size())
|
||||
if (!parent->writable)
|
||||
return result::ObjectInvalid;
|
||||
auto storageSpan{parent->GetSpan()};
|
||||
if (offset < 0 || offset > storageSpan.size())
|
||||
return result::OutOfBounds;
|
||||
|
||||
size_t size{std::min(request.inputBuf.at(0).size(), parent->content.size() - static_cast<size_t>(offset))};
|
||||
size_t size{std::min(request.inputBuf.at(0).size(), storageSpan.size() - static_cast<size_t>(offset))};
|
||||
|
||||
if (size)
|
||||
span(parent->content).copy_from(request.inputBuf.at(0), size);
|
||||
storageSpan.subspan(static_cast<size_t>(offset)).copy_from(request.inputBuf.at(0), size);
|
||||
|
||||
return {};
|
||||
}
|
||||
@ -29,13 +32,14 @@ namespace skyline::service::am {
|
||||
Result IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto offset{request.Pop<i64>()};
|
||||
|
||||
if (offset < 0 || offset > parent->content.size())
|
||||
auto storageSpan{parent->GetSpan()};
|
||||
if (offset < 0 || offset > storageSpan.size())
|
||||
return result::OutOfBounds;
|
||||
|
||||
size_t size{std::min(request.outputBuf.at(0).size(), parent->content.size() - static_cast<size_t>(offset))};
|
||||
size_t size{std::min(request.outputBuf.at(0).size(), storageSpan.size() - static_cast<size_t>(offset))};
|
||||
|
||||
if (size)
|
||||
request.outputBuf.at(0).copy_from(span(parent->content.data() + offset, size));
|
||||
request.outputBuf.at(0).copy_from(span(storageSpan.data() + offset, size));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
namespace skyline::service::am {
|
||||
namespace result {
|
||||
constexpr Result ObjectInvalid(128, 500);
|
||||
constexpr Result OutOfBounds(128, 503);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "TransferMemoryIStorage.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace skyline::service::am {
|
||||
TransferMemoryIStorage::TransferMemoryIStorage(const DeviceState &state, ServiceManager &manager, std::shared_ptr<kernel::type::KTransferMemory> transferMemory, bool writable) : transferMemory(std::move(transferMemory)), IStorage(state, manager, writable) {}
|
||||
|
||||
span<u8> TransferMemoryIStorage::GetSpan() {
|
||||
return transferMemory->Get();
|
||||
}
|
||||
|
||||
TransferMemoryIStorage::~TransferMemoryIStorage() = default;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <services/serviceman.h>
|
||||
#include <kernel/types/KTransferMemory.h>
|
||||
#include "IStorage.h"
|
||||
|
||||
namespace skyline::service::am {
|
||||
/**
|
||||
* @brief An IStorage backed by a transfer memory supplied by the guest
|
||||
*/
|
||||
class TransferMemoryIStorage : public IStorage {
|
||||
private:
|
||||
std::shared_ptr<kernel::type::KTransferMemory> transferMemory;
|
||||
|
||||
public:
|
||||
|
||||
TransferMemoryIStorage(const DeviceState &state, ServiceManager &manager, std::shared_ptr<kernel::type::KTransferMemory> transferMemory, bool writable);
|
||||
|
||||
~TransferMemoryIStorage() override;
|
||||
|
||||
virtual span<u8> GetSpan() override;
|
||||
};
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "VectorIStorage.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace skyline::service::am {
|
||||
VectorIStorage::VectorIStorage(const DeviceState &state, ServiceManager &manager, size_t size) : content(size, 0), IStorage(state, manager, true) {}
|
||||
|
||||
VectorIStorage::VectorIStorage(const DeviceState &state, ServiceManager &manager, std::vector<u8> data) : content(std::move(data)), IStorage(state, manager, true) {}
|
||||
|
||||
span<u8> VectorIStorage::GetSpan() {
|
||||
return content;
|
||||
}
|
||||
|
||||
VectorIStorage::~VectorIStorage() = default;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <services/serviceman.h>
|
||||
#include "IStorage.h"
|
||||
|
||||
namespace skyline::service::am {
|
||||
/**
|
||||
* @brief VectorIStorage is an IStorage backed by a vector
|
||||
*/
|
||||
class VectorIStorage : public IStorage {
|
||||
private:
|
||||
std::vector<u8> content;
|
||||
|
||||
public:
|
||||
VectorIStorage(const DeviceState &state, ServiceManager &manager, size_t size);
|
||||
|
||||
VectorIStorage(const DeviceState &state, ServiceManager &manager, std::vector<u8> data);
|
||||
|
||||
~VectorIStorage() override;
|
||||
|
||||
virtual span<u8> GetSpan() override;
|
||||
};
|
||||
}
|
30
app/src/main/cpp/skyline/services/applet/common_arguments.h
Normal file
30
app/src/main/cpp/skyline/services/applet/common_arguments.h
Normal file
@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace skyline::service::applet {
|
||||
/**
|
||||
* @brief Specifies how the applet should run
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#LibraryAppletMode
|
||||
*/
|
||||
enum class LibraryAppletMode : u32 {
|
||||
AllForeground = 0x0,
|
||||
PartialForeground = 0x1,
|
||||
NoUi = 0x2,
|
||||
PartialForegroundWithIndirectDisplay = 0x3,
|
||||
AllForegroundInitiallyHidden = 0x4,
|
||||
};
|
||||
/**
|
||||
* @brief Common arguments to all LibraryApplets
|
||||
* @url https://switchbrew.org/wiki/Applet_Manager_services#CommonArguments
|
||||
*/
|
||||
struct CommonArguments {
|
||||
u32 version;
|
||||
u32 size;
|
||||
u32 apiVersion;
|
||||
u32 themeColor;
|
||||
u64 playStartupSound;
|
||||
u64 systemTick;
|
||||
};
|
||||
}
|
@ -40,7 +40,7 @@ namespace skyline::service {
|
||||
/**
|
||||
* @brief The base class for the HOS service interfaces hosted by sysmodules
|
||||
*/
|
||||
class BaseService {
|
||||
class BaseService : public std::enable_shared_from_this<BaseService> {
|
||||
private:
|
||||
std::string name; //!< The name of the service, it's only assigned after GetName is called and shouldn't be used directly
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user