mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-23 04:59:16 +01:00
Refactor service functions to return result codes
This commit is contained in:
parent
74a150dff1
commit
89718804d0
@ -25,6 +25,32 @@
|
|||||||
namespace skyline {
|
namespace skyline {
|
||||||
using KHandle = u32; //!< The type of a kernel handle
|
using KHandle = u32; //!< The type of a kernel handle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The result of an operation in HOS
|
||||||
|
* @url https://switchbrew.org/wiki/Error_codes
|
||||||
|
*/
|
||||||
|
union Result {
|
||||||
|
u32 raw{};
|
||||||
|
struct {
|
||||||
|
u16 module : 9;
|
||||||
|
u16 id : 12;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @note Success is 0, 0 - it is the only error that's not specific to a module
|
||||||
|
*/
|
||||||
|
Result() {}
|
||||||
|
|
||||||
|
constexpr Result(u16 module, u16 id) {
|
||||||
|
this->module = module;
|
||||||
|
this->id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr operator u32() const {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace constant {
|
namespace constant {
|
||||||
// Memory
|
// Memory
|
||||||
constexpr u64 BaseAddress = 0x8000000; //!< The address space base
|
constexpr u64 BaseAddress = 0x8000000; //!< The address space base
|
||||||
@ -36,29 +62,6 @@ namespace skyline {
|
|||||||
constexpr u16 DockedResolutionH = 1080; //!< The height component of the docked resolution
|
constexpr u16 DockedResolutionH = 1080; //!< The height component of the docked resolution
|
||||||
// Time
|
// Time
|
||||||
constexpr u64 NsInSecond = 1000000000; //!< This is the amount of nanoseconds in a second
|
constexpr u64 NsInSecond = 1000000000; //!< This is the amount of nanoseconds in a second
|
||||||
// Status codes
|
|
||||||
namespace status {
|
|
||||||
constexpr u32 Success = 0x0; //!< "Success"
|
|
||||||
constexpr u32 PathDoesNotExist = 0x202; //!< "Path does not exist"
|
|
||||||
constexpr u32 GenericError = 0x272; //!< "Generic error"
|
|
||||||
constexpr u32 NoMessages = 0x680; //!< "No message available"
|
|
||||||
constexpr u32 ServiceInvName = 0xC15; //!< "Invalid name"
|
|
||||||
constexpr u32 ServiceNotReg = 0xE15; //!< "Service not registered"
|
|
||||||
constexpr u32 InvUser = 0xC87C; //!< Invalid user
|
|
||||||
constexpr u32 InvSize = 0xCA01; //!< "Invalid size"
|
|
||||||
constexpr u32 InvAddress = 0xCC01; //!< "Invalid address"
|
|
||||||
constexpr u32 InvState = 0xD401; //!< "Invalid MemoryState"
|
|
||||||
constexpr u32 InvPermission = 0xD801; //!< "Invalid Permission"
|
|
||||||
constexpr u32 InvMemRange = 0xD801; //!< "Invalid Memory Range"
|
|
||||||
constexpr u32 InvPriority = 0xE001; //!< "Invalid Priority"
|
|
||||||
constexpr u32 InvHandle = 0xE401; //!< "Invalid handle"
|
|
||||||
constexpr u32 InvCombination = 0xE801; //!< "Invalid combination"
|
|
||||||
constexpr u32 Timeout = 0xEA01; //!< "Timeout"
|
|
||||||
constexpr u32 Interrupted = 0xEC01; //!< "Interrupted"
|
|
||||||
constexpr u32 MaxHandles = 0xEE01; //!< "Too many handles"
|
|
||||||
constexpr u32 NotFound = 0xF201; //!< "Not found"
|
|
||||||
constexpr u32 Unimpl = 0x177202; //!< "Unimplemented behaviour"
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
@ -309,7 +309,7 @@ namespace skyline {
|
|||||||
std::vector<u8> payload; //!< This holds all of the contents to be pushed to the payload
|
std::vector<u8> payload; //!< This holds all of the contents to be pushed to the payload
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u32 errorCode{}; //!< The error code to respond with, it is 0 (Success) by default
|
Result errorCode{}; //!< The error code to respond with, it is 0 (Success) by default
|
||||||
std::vector<KHandle> copyHandles; //!< A vector of handles to copy
|
std::vector<KHandle> copyHandles; //!< A vector of handles to copy
|
||||||
std::vector<KHandle> moveHandles; //!< A vector of handles to move
|
std::vector<KHandle> moveHandles; //!< A vector of handles to move
|
||||||
std::vector<KHandle> domainObjects; //!< A vector of domain objects to write
|
std::vector<KHandle> domainObjects; //!< A vector of domain objects to write
|
||||||
|
53
app/src/main/cpp/skyline/kernel/results.h
Normal file
53
app/src/main/cpp/skyline/kernel/results.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
namespace skyline::kernel::result {
|
||||||
|
constexpr Result OutOfSessions(1, 7);
|
||||||
|
constexpr Result InvalidArgument(1, 14);
|
||||||
|
constexpr Result NotImplemented(1, 33);
|
||||||
|
constexpr Result StopProcessingException(1, 54);
|
||||||
|
constexpr Result NoSynchronizationObject(1, 57);
|
||||||
|
constexpr Result TerminationRequested(1, 59);
|
||||||
|
constexpr Result NoEvent(1, 70);
|
||||||
|
constexpr Result InvalidSize(1, 101);
|
||||||
|
constexpr Result InvalidAddress(1, 102);
|
||||||
|
constexpr Result OutOfResource(1, 103);
|
||||||
|
constexpr Result OutOfMemory(1, 104);
|
||||||
|
constexpr Result OutOfHandles(1, 105);
|
||||||
|
constexpr Result InvalidCurrentMemory(1, 106);
|
||||||
|
constexpr Result InvalidNewMemoryPermission(1, 108);
|
||||||
|
constexpr Result InvalidMemoryRegion(1, 110);
|
||||||
|
constexpr Result InvalidPriority(1, 112);
|
||||||
|
constexpr Result InvalidCoreId(1, 113);
|
||||||
|
constexpr Result InvalidHandle(1, 114);
|
||||||
|
constexpr Result InvalidPointer(1, 115);
|
||||||
|
constexpr Result InvalidCombination(1, 116);
|
||||||
|
constexpr Result TimedOut(1, 117);
|
||||||
|
constexpr Result Cancelled(1, 118);
|
||||||
|
constexpr Result OutOfRange(1, 119);
|
||||||
|
constexpr Result InvalidEnumValue(1, 120);
|
||||||
|
constexpr Result NotFound(1, 121);
|
||||||
|
constexpr Result Busy(1, 122);
|
||||||
|
constexpr Result SessionClosed(1, 123);
|
||||||
|
constexpr Result NotHandled(1, 124);
|
||||||
|
constexpr Result InvalidState(1, 125);
|
||||||
|
constexpr Result ReservedUsed(1, 126);
|
||||||
|
constexpr Result NotSupported(1, 127);
|
||||||
|
constexpr Result Debug(1, 128);
|
||||||
|
constexpr Result NoThread(1, 129);
|
||||||
|
constexpr Result UnknownThread(1, 130);
|
||||||
|
constexpr Result PortClosed(1, 131);
|
||||||
|
constexpr Result LimitReached(1, 132);
|
||||||
|
constexpr Result InvalidMemoryPool(1, 133);
|
||||||
|
constexpr Result ReceiveListBroken(1, 258);
|
||||||
|
constexpr Result OutOfAddressSpace(1, 259);
|
||||||
|
constexpr Result MessageTooLarge(1, 260);
|
||||||
|
constexpr Result InvalidProcessId(1, 517);
|
||||||
|
constexpr Result InvalidThreadId(1, 518);
|
||||||
|
constexpr Result InvalidId(1, 519);
|
||||||
|
constexpr Result ProcessTerminated(1, 520);
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
#include <os.h>
|
#include <os.h>
|
||||||
|
#include "results.h"
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
namespace skyline::kernel::svc {
|
namespace skyline::kernel::svc {
|
||||||
@ -9,7 +10,7 @@ namespace skyline::kernel::svc {
|
|||||||
auto size = state.ctx->registers.w1;
|
auto size = state.ctx->registers.w1;
|
||||||
|
|
||||||
if (!util::IsAligned(size, 0x200000)) {
|
if (!util::IsAligned(size, 0x200000)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = result::InvalidSize;
|
||||||
state.ctx->registers.x1 = 0;
|
state.ctx->registers.x1 = 0;
|
||||||
|
|
||||||
state.logger->Warn("svcSetHeapSize: 'size' not divisible by 2MB: {}", size);
|
state.logger->Warn("svcSetHeapSize: 'size' not divisible by 2MB: {}", size);
|
||||||
@ -19,7 +20,7 @@ namespace skyline::kernel::svc {
|
|||||||
auto &heap = state.process->heap;
|
auto &heap = state.process->heap;
|
||||||
heap->Resize(size);
|
heap->Resize(size);
|
||||||
|
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
state.ctx->registers.x1 = heap->address;
|
state.ctx->registers.x1 = heap->address;
|
||||||
|
|
||||||
state.logger->Debug("svcSetHeapSize: Allocated at 0x{:X} for 0x{:X} bytes", heap->address, heap->size);
|
state.logger->Debug("svcSetHeapSize: Allocated at 0x{:X} for 0x{:X} bytes", heap->address, heap->size);
|
||||||
@ -28,14 +29,14 @@ namespace skyline::kernel::svc {
|
|||||||
void SetMemoryAttribute(DeviceState &state) {
|
void SetMemoryAttribute(DeviceState &state) {
|
||||||
auto address = state.ctx->registers.x0;
|
auto address = state.ctx->registers.x0;
|
||||||
if (!util::PageAligned(address)) {
|
if (!util::PageAligned(address)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcSetMemoryAttribute: 'address' not page aligned: 0x{:X}", address);
|
state.logger->Warn("svcSetMemoryAttribute: 'address' not page aligned: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size = state.ctx->registers.x1;
|
auto size = state.ctx->registers.x1;
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("svcSetMemoryAttribute: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcSetMemoryAttribute: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -45,7 +46,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
auto maskedValue = mask.value | value.value;
|
auto maskedValue = mask.value | value.value;
|
||||||
if (maskedValue != mask.value || !mask.isUncached || mask.isDeviceShared || mask.isBorrowed || mask.isIpcLocked) {
|
if (maskedValue != mask.value || !mask.isUncached || mask.isDeviceShared || mask.isBorrowed || mask.isIpcLocked) {
|
||||||
state.ctx->registers.w0 = constant::status::InvCombination;
|
state.ctx->registers.w0 = result::InvalidCombination;
|
||||||
state.logger->Warn("svcSetMemoryAttribute: 'mask' invalid: 0x{:X}, 0x{:X}", mask.value, value.value);
|
state.logger->Warn("svcSetMemoryAttribute: 'mask' invalid: 0x{:X}, 0x{:X}", mask.value, value.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,13 +54,13 @@ namespace skyline::kernel::svc {
|
|||||||
auto chunk = state.os->memory.GetChunk(address);
|
auto chunk = state.os->memory.GetChunk(address);
|
||||||
auto block = state.os->memory.GetBlock(address);
|
auto block = state.os->memory.GetBlock(address);
|
||||||
if (!chunk || !block) {
|
if (!chunk || !block) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcSetMemoryAttribute: Cannot find memory region: 0x{:X}", address);
|
state.logger->Warn("svcSetMemoryAttribute: Cannot find memory region: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chunk->state.attributeChangeAllowed) {
|
if (!chunk->state.attributeChangeAllowed) {
|
||||||
state.ctx->registers.w0 = constant::status::InvState;
|
state.ctx->registers.w0 = result::InvalidState;
|
||||||
state.logger->Warn("svcSetMemoryAttribute: Attribute change not allowed for chunk: 0x{:X}", address);
|
state.logger->Warn("svcSetMemoryAttribute: Attribute change not allowed for chunk: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -68,7 +69,7 @@ namespace skyline::kernel::svc {
|
|||||||
MemoryManager::InsertBlock(chunk, *block);
|
MemoryManager::InsertBlock(chunk, *block);
|
||||||
|
|
||||||
state.logger->Debug("svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes", !block->attributes.isUncached, address, size);
|
state.logger->Debug("svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes", !block->attributes.isUncached, address, size);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapMemory(DeviceState &state) {
|
void MapMemory(DeviceState &state) {
|
||||||
@ -77,32 +78,32 @@ namespace skyline::kernel::svc {
|
|||||||
auto size = state.ctx->registers.x2;
|
auto size = state.ctx->registers.x2;
|
||||||
|
|
||||||
if (!util::PageAligned(destination) || !util::PageAligned(source)) {
|
if (!util::PageAligned(destination) || !util::PageAligned(source)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcMapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
state.logger->Warn("svcMapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("svcMapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcMapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stack = state.os->memory.stack;
|
auto stack = state.os->memory.stack;
|
||||||
if (!stack.IsInside(destination)) {
|
if (!stack.IsInside(destination)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvMemRange;
|
state.ctx->registers.w0 = result::InvalidMemoryRegion;
|
||||||
state.logger->Warn("svcMapMemory: Destination not within stack region: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
state.logger->Warn("svcMapMemory: Destination not within stack region: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto descriptor = state.os->memory.Get(source);
|
auto descriptor = state.os->memory.Get(source);
|
||||||
if (!descriptor) {
|
if (!descriptor) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcMapMemory: Source has no descriptor: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
state.logger->Warn("svcMapMemory: Source has no descriptor: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!descriptor->chunk.state.mapAllowed) {
|
if (!descriptor->chunk.state.mapAllowed) {
|
||||||
state.ctx->registers.w0 = constant::status::InvState;
|
state.ctx->registers.w0 = result::InvalidState;
|
||||||
state.logger->Warn("svcMapMemory: Source doesn't allow usage of svcMapMemory: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) 0x{:X}", source, destination, size, descriptor->chunk.state.value);
|
state.logger->Warn("svcMapMemory: Source doesn't allow usage of svcMapMemory: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) 0x{:X}", source, destination, size, descriptor->chunk.state.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -117,7 +118,7 @@ namespace skyline::kernel::svc {
|
|||||||
object->item->UpdatePermission(source, size, {false, false, false});
|
object->item->UpdatePermission(source, size, {false, false, false});
|
||||||
|
|
||||||
state.logger->Debug("svcMapMemory: Mapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size);
|
state.logger->Debug("svcMapMemory: Mapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnmapMemory(DeviceState &state) {
|
void UnmapMemory(DeviceState &state) {
|
||||||
@ -126,20 +127,20 @@ namespace skyline::kernel::svc {
|
|||||||
auto size = state.ctx->registers.x2;
|
auto size = state.ctx->registers.x2;
|
||||||
|
|
||||||
if (!util::PageAligned(destination) || !util::PageAligned(source)) {
|
if (!util::PageAligned(destination) || !util::PageAligned(source)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcUnmapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
state.logger->Warn("svcUnmapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("svcUnmapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcUnmapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stack = state.os->memory.stack;
|
auto stack = state.os->memory.stack;
|
||||||
if (!stack.IsInside(source)) {
|
if (!stack.IsInside(source)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvMemRange;
|
state.ctx->registers.w0 = result::InvalidMemoryRegion;
|
||||||
state.logger->Warn("svcUnmapMemory: Source not within stack region: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
state.logger->Warn("svcUnmapMemory: Source not within stack region: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -147,13 +148,13 @@ namespace skyline::kernel::svc {
|
|||||||
auto sourceDesc = state.os->memory.Get(source);
|
auto sourceDesc = state.os->memory.Get(source);
|
||||||
auto destDesc = state.os->memory.Get(destination);
|
auto destDesc = state.os->memory.Get(destination);
|
||||||
if (!sourceDesc || !destDesc) {
|
if (!sourceDesc || !destDesc) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcUnmapMemory: Addresses have no descriptor: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
state.logger->Warn("svcUnmapMemory: Addresses have no descriptor: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!destDesc->chunk.state.mapAllowed) {
|
if (!destDesc->chunk.state.mapAllowed) {
|
||||||
state.ctx->registers.w0 = constant::status::InvState;
|
state.ctx->registers.w0 = result::InvalidState;
|
||||||
state.logger->Warn("svcUnmapMemory: Destination doesn't allow usage of svcMapMemory: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) 0x{:X}", source, destination, size, destDesc->chunk.state.value);
|
state.logger->Warn("svcUnmapMemory: Destination doesn't allow usage of svcMapMemory: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) 0x{:X}", source, destination, size, destDesc->chunk.state.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -173,7 +174,7 @@ namespace skyline::kernel::svc {
|
|||||||
state.process->DeleteHandle(sourceObject->handle);
|
state.process->DeleteHandle(sourceObject->handle);
|
||||||
|
|
||||||
state.logger->Debug("svcUnmapMemory: Unmapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size);
|
state.logger->Debug("svcUnmapMemory: Unmapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes)", source, source + size, destination, destination + size, size);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryMemory(DeviceState &state) {
|
void QueryMemory(DeviceState &state) {
|
||||||
@ -208,7 +209,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
state.process->WriteMemory(memInfo, state.ctx->registers.x0);
|
state.process->WriteMemory(memInfo, state.ctx->registers.x0);
|
||||||
|
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExitProcess(DeviceState &state) {
|
void ExitProcess(DeviceState &state) {
|
||||||
@ -223,7 +224,7 @@ namespace skyline::kernel::svc {
|
|||||||
auto priority = static_cast<i8>(state.ctx->registers.w4);
|
auto priority = static_cast<i8>(state.ctx->registers.w4);
|
||||||
|
|
||||||
if (!state.thread->switchPriority.Valid(priority)) {
|
if (!state.thread->switchPriority.Valid(priority)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcCreateThread: 'priority' invalid: {}", priority);
|
state.logger->Warn("svcCreateThread: 'priority' invalid: {}", priority);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -232,7 +233,7 @@ namespace skyline::kernel::svc {
|
|||||||
state.logger->Debug("svcCreateThread: Created thread with handle 0x{:X} (Entry Point: 0x{:X}, Argument: 0x{:X}, Stack Pointer: 0x{:X}, Priority: {}, TID: {})", thread->handle, entryAddress, entryArgument, stackTop, priority, thread->tid);
|
state.logger->Debug("svcCreateThread: Created thread with handle 0x{:X} (Entry Point: 0x{:X}, Argument: 0x{:X}, Stack Pointer: 0x{:X}, Priority: {}, TID: {})", thread->handle, entryAddress, entryArgument, stackTop, priority, thread->tid);
|
||||||
|
|
||||||
state.ctx->registers.w1 = thread->handle;
|
state.ctx->registers.w1 = thread->handle;
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartThread(DeviceState &state) {
|
void StartThread(DeviceState &state) {
|
||||||
@ -241,10 +242,10 @@ namespace skyline::kernel::svc {
|
|||||||
auto thread = state.process->GetHandle<type::KThread>(handle);
|
auto thread = state.process->GetHandle<type::KThread>(handle);
|
||||||
state.logger->Debug("svcStartThread: Starting thread: 0x{:X}, PID: {}", handle, thread->tid);
|
state.logger->Debug("svcStartThread: Starting thread: 0x{:X}, PID: {}", handle, thread->tid);
|
||||||
thread->Start();
|
thread->Start();
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
state.logger->Warn("svcStartThread: 'handle' invalid: 0x{:X}", handle);
|
state.logger->Warn("svcStartThread: 'handle' invalid: 0x{:X}", handle);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,10 +280,10 @@ namespace skyline::kernel::svc {
|
|||||||
state.logger->Debug("svcGetThreadPriority: Writing thread priority {}", priority);
|
state.logger->Debug("svcGetThreadPriority: Writing thread priority {}", priority);
|
||||||
|
|
||||||
state.ctx->registers.w1 = priority;
|
state.ctx->registers.w1 = priority;
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
state.logger->Warn("svcGetThreadPriority: 'handle' invalid: 0x{:X}", handle);
|
state.logger->Warn("svcGetThreadPriority: 'handle' invalid: 0x{:X}", handle);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,17 +294,17 @@ namespace skyline::kernel::svc {
|
|||||||
try {
|
try {
|
||||||
state.logger->Debug("svcSetThreadPriority: Setting thread priority to {}", priority);
|
state.logger->Debug("svcSetThreadPriority: Setting thread priority to {}", priority);
|
||||||
state.process->GetHandle<type::KThread>(handle)->UpdatePriority(static_cast<u8>(priority));
|
state.process->GetHandle<type::KThread>(handle)->UpdatePriority(static_cast<u8>(priority));
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
state.logger->Warn("svcSetThreadPriority: 'handle' invalid: 0x{:X}", handle);
|
state.logger->Warn("svcSetThreadPriority: 'handle' invalid: 0x{:X}", handle);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearEvent(DeviceState &state) {
|
void ClearEvent(DeviceState &state) {
|
||||||
auto object = state.process->GetHandle<type::KEvent>(state.ctx->registers.w0);
|
auto object = state.process->GetHandle<type::KEvent>(state.ctx->registers.w0);
|
||||||
object->signalled = false;
|
object->signalled = false;
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapSharedMemory(DeviceState &state) {
|
void MapSharedMemory(DeviceState &state) {
|
||||||
@ -312,14 +313,14 @@ namespace skyline::kernel::svc {
|
|||||||
auto address = state.ctx->registers.x1;
|
auto address = state.ctx->registers.x1;
|
||||||
|
|
||||||
if (!util::PageAligned(address)) {
|
if (!util::PageAligned(address)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcMapSharedMemory: 'address' not page aligned: 0x{:X}", address);
|
state.logger->Warn("svcMapSharedMemory: 'address' not page aligned: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size = state.ctx->registers.x2;
|
auto size = state.ctx->registers.x2;
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("svcMapSharedMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcMapSharedMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -327,7 +328,7 @@ namespace skyline::kernel::svc {
|
|||||||
memory::Permission permission = *reinterpret_cast<memory::Permission *>(&state.ctx->registers.w3);
|
memory::Permission permission = *reinterpret_cast<memory::Permission *>(&state.ctx->registers.w3);
|
||||||
if ((permission.w && !permission.r) || (permission.x && !permission.r)) {
|
if ((permission.w && !permission.r) || (permission.x && !permission.r)) {
|
||||||
state.logger->Warn("svcMapSharedMemory: 'permission' invalid: {}{}{}", permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-");
|
state.logger->Warn("svcMapSharedMemory: 'permission' invalid: {}{}{}", permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-");
|
||||||
state.ctx->registers.w0 = constant::status::InvPermission;
|
state.ctx->registers.w0 = result::InvalidNewMemoryPermission;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,24 +336,24 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
object->Map(address, size, permission);
|
object->Map(address, size, permission);
|
||||||
|
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
state.logger->Warn("svcMapSharedMemory: 'handle' invalid: 0x{:X}", state.ctx->registers.w0);
|
state.logger->Warn("svcMapSharedMemory: 'handle' invalid: 0x{:X}", state.ctx->registers.w0);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateTransferMemory(DeviceState &state) {
|
void CreateTransferMemory(DeviceState &state) {
|
||||||
auto address = state.ctx->registers.x1;
|
auto address = state.ctx->registers.x1;
|
||||||
if (!util::PageAligned(address)) {
|
if (!util::PageAligned(address)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("svcCreateTransferMemory: 'address' not page aligned: 0x{:X}", address);
|
state.logger->Warn("svcCreateTransferMemory: 'address' not page aligned: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size = state.ctx->registers.x2;
|
auto size = state.ctx->registers.x2;
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("svcCreateTransferMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcCreateTransferMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -360,7 +361,7 @@ namespace skyline::kernel::svc {
|
|||||||
memory::Permission permission = *reinterpret_cast<memory::Permission *>(&state.ctx->registers.w3);
|
memory::Permission permission = *reinterpret_cast<memory::Permission *>(&state.ctx->registers.w3);
|
||||||
if ((permission.w && !permission.r) || (permission.x && !permission.r)) {
|
if ((permission.w && !permission.r) || (permission.x && !permission.r)) {
|
||||||
state.logger->Warn("svcCreateTransferMemory: 'permission' invalid: {}{}{}", permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-");
|
state.logger->Warn("svcCreateTransferMemory: 'permission' invalid: {}{}{}", permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-");
|
||||||
state.ctx->registers.w0 = constant::status::InvPermission;
|
state.ctx->registers.w0 = result::InvalidNewMemoryPermission;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +369,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
auto shmem = state.process->NewHandle<type::KTransferMemory>(state.process->pid, address, size, permission);
|
auto shmem = state.process->NewHandle<type::KTransferMemory>(state.process->pid, address, size, permission);
|
||||||
|
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
state.ctx->registers.w1 = shmem.handle;
|
state.ctx->registers.w1 = shmem.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,10 +378,10 @@ namespace skyline::kernel::svc {
|
|||||||
try {
|
try {
|
||||||
state.process->handles.erase(handle);
|
state.process->handles.erase(handle);
|
||||||
state.logger->Debug("svcCloseHandle: Closing handle: 0x{:X}", handle);
|
state.logger->Debug("svcCloseHandle: Closing handle: 0x{:X}", handle);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
state.logger->Warn("svcCloseHandle: 'handle' invalid: 0x{:X}", handle);
|
state.logger->Warn("svcCloseHandle: 'handle' invalid: 0x{:X}", handle);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,16 +400,16 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
state.logger->Warn("svcResetSignal: 'handle' type invalid: 0x{:X} ({})", handle, object->objectType);
|
state.logger->Warn("svcResetSignal: 'handle' type invalid: 0x{:X} ({})", handle, object->objectType);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.logger->Debug("svcResetSignal: Resetting signal: 0x{:X}", handle);
|
state.logger->Debug("svcResetSignal: Resetting signal: 0x{:X}", handle);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} catch (const std::out_of_range &) {
|
} catch (const std::out_of_range &) {
|
||||||
state.logger->Warn("svcResetSignal: 'handle' invalid: 0x{:X}", handle);
|
state.logger->Warn("svcResetSignal: 'handle' invalid: 0x{:X}", handle);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -418,7 +419,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
auto numHandles = state.ctx->registers.w2;
|
auto numHandles = state.ctx->registers.w2;
|
||||||
if (numHandles > maxSyncHandles) {
|
if (numHandles > maxSyncHandles) {
|
||||||
state.ctx->registers.w0 = constant::status::MaxHandles;
|
state.ctx->registers.w0 = result::OutOfHandles;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +441,7 @@ namespace skyline::kernel::svc {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,7 +456,7 @@ namespace skyline::kernel::svc {
|
|||||||
while (true) {
|
while (true) {
|
||||||
if (state.thread->cancelSync) {
|
if (state.thread->cancelSync) {
|
||||||
state.thread->cancelSync = false;
|
state.thread->cancelSync = false;
|
||||||
state.ctx->registers.w0 = constant::status::Interrupted;
|
state.ctx->registers.w0 = result::Cancelled;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +464,7 @@ namespace skyline::kernel::svc {
|
|||||||
for (const auto &object : objectTable) {
|
for (const auto &object : objectTable) {
|
||||||
if (object->signalled) {
|
if (object->signalled) {
|
||||||
state.logger->Debug("svcWaitSynchronization: Signalled handle: 0x{:X}", waitHandles.at(index));
|
state.logger->Debug("svcWaitSynchronization: Signalled handle: 0x{:X}", waitHandles.at(index));
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
state.ctx->registers.w1 = index;
|
state.ctx->registers.w1 = index;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -472,7 +473,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
if ((util::GetTimeNs() - start) >= timeout) {
|
if ((util::GetTimeNs() - start) >= timeout) {
|
||||||
state.logger->Debug("svcWaitSynchronization: Wait has timed out");
|
state.logger->Debug("svcWaitSynchronization: Wait has timed out");
|
||||||
state.ctx->registers.w0 = constant::status::Timeout;
|
state.ctx->registers.w0 = result::TimedOut;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,7 +484,7 @@ namespace skyline::kernel::svc {
|
|||||||
state.process->GetHandle<type::KThread>(state.ctx->registers.w0)->cancelSync = true;
|
state.process->GetHandle<type::KThread>(state.ctx->registers.w0)->cancelSync = true;
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
state.logger->Warn("svcCancelSynchronization: 'handle' invalid: 0x{:X}", state.ctx->registers.w0);
|
state.logger->Warn("svcCancelSynchronization: 'handle' invalid: 0x{:X}", state.ctx->registers.w0);
|
||||||
state.ctx->registers.w0 = constant::status::InvHandle;
|
state.ctx->registers.w0 = result::InvalidHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,7 +492,7 @@ namespace skyline::kernel::svc {
|
|||||||
auto address = state.ctx->registers.x1;
|
auto address = state.ctx->registers.x1;
|
||||||
if (!util::WordAligned(address)) {
|
if (!util::WordAligned(address)) {
|
||||||
state.logger->Warn("svcArbitrateLock: 'address' not word aligned: 0x{:X}", address);
|
state.logger->Warn("svcArbitrateLock: 'address' not word aligned: 0x{:X}", address);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,14 +508,14 @@ namespace skyline::kernel::svc {
|
|||||||
else
|
else
|
||||||
state.logger->Debug("svcArbitrateLock: Owner handle did not match current owner for mutex or didn't have waiter flag at 0x{:X}", address);
|
state.logger->Debug("svcArbitrateLock: Owner handle did not match current owner for mutex or didn't have waiter flag at 0x{:X}", address);
|
||||||
|
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArbitrateUnlock(DeviceState &state) {
|
void ArbitrateUnlock(DeviceState &state) {
|
||||||
auto address = state.ctx->registers.x0;
|
auto address = state.ctx->registers.x0;
|
||||||
if (!util::WordAligned(address)) {
|
if (!util::WordAligned(address)) {
|
||||||
state.logger->Warn("svcArbitrateUnlock: 'address' not word aligned: 0x{:X}", address);
|
state.logger->Warn("svcArbitrateUnlock: 'address' not word aligned: 0x{:X}", address);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,10 +523,10 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
if (state.process->MutexUnlock(address)) {
|
if (state.process->MutexUnlock(address)) {
|
||||||
state.logger->Debug("svcArbitrateUnlock: Unlocked mutex at 0x{:X}", address);
|
state.logger->Debug("svcArbitrateUnlock: Unlocked mutex at 0x{:X}", address);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} else {
|
} else {
|
||||||
state.logger->Debug("svcArbitrateUnlock: A non-owner thread tried to release a mutex at 0x{:X}", address);
|
state.logger->Debug("svcArbitrateUnlock: A non-owner thread tried to release a mutex at 0x{:X}", address);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,7 +534,7 @@ namespace skyline::kernel::svc {
|
|||||||
auto mtxAddress = state.ctx->registers.x0;
|
auto mtxAddress = state.ctx->registers.x0;
|
||||||
if (!util::WordAligned(mtxAddress)) {
|
if (!util::WordAligned(mtxAddress)) {
|
||||||
state.logger->Warn("svcWaitProcessWideKeyAtomic: mutex address not word aligned: 0x{:X}", mtxAddress);
|
state.logger->Warn("svcWaitProcessWideKeyAtomic: mutex address not word aligned: 0x{:X}", mtxAddress);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,7 +545,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
if (!state.process->MutexUnlock(mtxAddress)) {
|
if (!state.process->MutexUnlock(mtxAddress)) {
|
||||||
state.logger->Debug("WaitProcessWideKeyAtomic: A non-owner thread tried to release a mutex at 0x{:X}", mtxAddress);
|
state.logger->Debug("WaitProcessWideKeyAtomic: A non-owner thread tried to release a mutex at 0x{:X}", mtxAddress);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,10 +554,10 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
if (state.process->ConditionalVariableWait(condAddress, mtxAddress, timeout)) {
|
if (state.process->ConditionalVariableWait(condAddress, mtxAddress, timeout)) {
|
||||||
state.logger->Debug("svcWaitProcessWideKeyAtomic: Waited for conditional variable and relocked mutex");
|
state.logger->Debug("svcWaitProcessWideKeyAtomic: Waited for conditional variable and relocked mutex");
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
} else {
|
} else {
|
||||||
state.logger->Debug("svcWaitProcessWideKeyAtomic: Wait has timed out");
|
state.logger->Debug("svcWaitProcessWideKeyAtomic: Wait has timed out");
|
||||||
state.ctx->registers.w0 = constant::status::Timeout;
|
state.ctx->registers.w0 = result::TimedOut;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,7 +567,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
state.logger->Debug("svcSignalProcessWideKey: Signalling Conditional-Variable at 0x{:X} for {}", address, count);
|
state.logger->Debug("svcSignalProcessWideKey: Signalling Conditional-Variable at 0x{:X} for {}", address, count);
|
||||||
state.process->ConditionalVariableSignal(address, count);
|
state.process->ConditionalVariableSignal(address, count);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetSystemTick(DeviceState &state) {
|
void GetSystemTick(DeviceState &state) {
|
||||||
@ -591,19 +592,19 @@ namespace skyline::kernel::svc {
|
|||||||
handle = state.process->NewHandle<type::KSession>(std::static_pointer_cast<service::BaseService>(state.os->serviceManager.smUserInterface)).handle;
|
handle = state.process->NewHandle<type::KSession>(std::static_pointer_cast<service::BaseService>(state.os->serviceManager.smUserInterface)).handle;
|
||||||
} else {
|
} else {
|
||||||
state.logger->Warn("svcConnectToNamedPort: Connecting to invalid port: '{}'", port);
|
state.logger->Warn("svcConnectToNamedPort: Connecting to invalid port: '{}'", port);
|
||||||
state.ctx->registers.w0 = constant::status::NotFound;
|
state.ctx->registers.w0 = result::NotFound;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.logger->Debug("svcConnectToNamedPort: Connecting to port '{}' at 0x{:X}", port, handle);
|
state.logger->Debug("svcConnectToNamedPort: Connecting to port '{}' at 0x{:X}", port, handle);
|
||||||
|
|
||||||
state.ctx->registers.w1 = handle;
|
state.ctx->registers.w1 = handle;
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSyncRequest(DeviceState &state) {
|
void SendSyncRequest(DeviceState &state) {
|
||||||
state.os->serviceManager.SyncRequestHandler(static_cast<KHandle>(state.ctx->registers.x0));
|
state.os->serviceManager.SyncRequestHandler(static_cast<KHandle>(state.ctx->registers.x0));
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetThreadId(DeviceState &state) {
|
void GetThreadId(DeviceState &state) {
|
||||||
@ -619,7 +620,7 @@ namespace skyline::kernel::svc {
|
|||||||
state.logger->Debug("svcGetThreadId: Handle: 0x{:X}, PID: {}", handle, pid);
|
state.logger->Debug("svcGetThreadId: Handle: 0x{:X}, PID: {}", handle, pid);
|
||||||
|
|
||||||
state.ctx->registers.x1 = static_cast<u64>(pid);
|
state.ctx->registers.x1 = static_cast<u64>(pid);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputDebugString(DeviceState &state) {
|
void OutputDebugString(DeviceState &state) {
|
||||||
@ -629,7 +630,7 @@ namespace skyline::kernel::svc {
|
|||||||
debug.pop_back();
|
debug.pop_back();
|
||||||
|
|
||||||
state.logger->Info("Debug Output: {}", debug);
|
state.logger->Info("Debug Output: {}", debug);
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetInfo(DeviceState &state) {
|
void GetInfo(DeviceState &state) {
|
||||||
@ -711,13 +712,13 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
state.logger->Warn("svcGetInfo: Unimplemented case ID0: {}, ID1: {}", id0, id1);
|
state.logger->Warn("svcGetInfo: Unimplemented case ID0: {}, ID1: {}", id0, id1);
|
||||||
state.ctx->registers.w0 = constant::status::Unimpl;
|
state.ctx->registers.w0 = result::InvalidEnumValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.logger->Debug("svcGetInfo: ID0: {}, ID1: {}, Out: 0x{:X}", id0, id1, out);
|
state.logger->Debug("svcGetInfo: ID0: {}, ID1: {}, Out: 0x{:X}", id0, id1, out);
|
||||||
|
|
||||||
state.ctx->registers.x1 = out;
|
state.ctx->registers.x1 = out;
|
||||||
state.ctx->registers.w0 = constant::status::Success;
|
state.ctx->registers.w0 = Result{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,22 +17,35 @@ namespace skyline::service::account {
|
|||||||
{0x65, SFUNC(IAccountServiceForApplication::GetBaasAccountManagerForApplication)}
|
{0x65, SFUNC(IAccountServiceForApplication::GetBaasAccountManagerForApplication)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IAccountServiceForApplication::GetUserExistence(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAccountServiceForApplication::GetUserExistence(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<UserId>();
|
auto id = request.Pop<UserId>();
|
||||||
|
|
||||||
|
// ID can't be zero
|
||||||
|
if (id == UserId{})
|
||||||
|
return result::NullArgument;
|
||||||
|
|
||||||
response.Push<u32>(id == constant::DefaultUserId);
|
response.Push<u32>(id == constant::DefaultUserId);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccountServiceForApplication::ListAllUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAccountServiceForApplication::ListAllUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
// We only support one active user currently so hardcode this and ListOpenUsers
|
try {
|
||||||
WriteUserList(request.outputBuf.at(0), {constant::DefaultUserId});
|
// We only support one active user currently so hardcode this and ListOpenUsers
|
||||||
|
return WriteUserList(request.outputBuf.at(0), {constant::DefaultUserId});
|
||||||
|
} catch (const std::out_of_range &e) {
|
||||||
|
return result::InvalidInputBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccountServiceForApplication::ListOpenUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAccountServiceForApplication::ListOpenUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
WriteUserList(request.outputBuf.at(0), {constant::DefaultUserId});
|
try {
|
||||||
|
return WriteUserList(request.outputBuf.at(0), {constant::DefaultUserId});
|
||||||
|
} catch (const std::out_of_range &e) {
|
||||||
|
return result::InvalidInputBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccountServiceForApplication::WriteUserList(ipc::OutputBuffer buffer, std::vector<UserId> userIds) {
|
Result IAccountServiceForApplication::WriteUserList(ipc::OutputBuffer buffer, std::vector<UserId> userIds) {
|
||||||
std::span outputUserIds(state.process->GetPointer<UserId>(buffer.address), buffer.size / sizeof(UserId));
|
std::span outputUserIds(state.process->GetPointer<UserId>(buffer.address), buffer.size / sizeof(UserId));
|
||||||
|
|
||||||
for (auto &userId : outputUserIds) {
|
for (auto &userId : outputUserIds) {
|
||||||
@ -43,25 +56,34 @@ namespace skyline::service::account {
|
|||||||
userIds.pop_back();
|
userIds.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccountServiceForApplication::GetLastOpenedUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAccountServiceForApplication::GetLastOpenedUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(constant::DefaultUserId);
|
response.Push(constant::DefaultUserId);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccountServiceForApplication::InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IAccountServiceForApplication::InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void IAccountServiceForApplication::GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAccountServiceForApplication::GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<UserId>();
|
auto id = request.Pop<UserId>();
|
||||||
if (id != constant::DefaultUserId) {
|
if (id != constant::DefaultUserId)
|
||||||
response.errorCode = constant::status::InvUser;
|
return result::UserNotFound;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager.RegisterService(std::make_shared<IProfile>(state, manager, id), session, response);
|
manager.RegisterService(std::make_shared<IProfile>(state, manager, id), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccountServiceForApplication::GetBaasAccountManagerForApplication(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAccountServiceForApplication::GetBaasAccountManagerForApplication(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
auto id = request.Pop<UserId>();
|
||||||
|
if (id == UserId{})
|
||||||
|
return result::NullArgument;
|
||||||
|
|
||||||
manager.RegisterService(SRVREG(IManagerForApplication), session, response);
|
manager.RegisterService(SRVREG(IManagerForApplication), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,13 @@
|
|||||||
|
|
||||||
namespace skyline {
|
namespace skyline {
|
||||||
namespace service::account {
|
namespace service::account {
|
||||||
|
namespace result {
|
||||||
|
constexpr Result NullArgument(124, 20);
|
||||||
|
constexpr Result InvalidArgument(124, 22);
|
||||||
|
constexpr Result InvalidInputBuffer(124, 32);
|
||||||
|
constexpr Result UserNotFound(124, 100);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This hold an account's user ID
|
* @brief This hold an account's user ID
|
||||||
*/
|
*/
|
||||||
@ -31,7 +38,7 @@ namespace skyline {
|
|||||||
/**
|
/**
|
||||||
* @brief Writes a vector of 128-bit user IDs to an output buffer
|
* @brief Writes a vector of 128-bit user IDs to an output buffer
|
||||||
*/
|
*/
|
||||||
void WriteUserList(ipc::OutputBuffer buffer, std::vector<UserId> userIds);
|
Result WriteUserList(ipc::OutputBuffer buffer, std::vector<UserId> userIds);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IAccountServiceForApplication(const DeviceState &state, ServiceManager &manager);
|
IAccountServiceForApplication(const DeviceState &state, ServiceManager &manager);
|
||||||
@ -39,37 +46,37 @@ namespace skyline {
|
|||||||
/**
|
/**
|
||||||
* @brief This checks if the given user ID exists
|
* @brief This checks if the given user ID exists
|
||||||
*/
|
*/
|
||||||
void GetUserExistence(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetUserExistence(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a list of all user accounts on the console
|
* @brief This returns a list of all user accounts on the console
|
||||||
*/
|
*/
|
||||||
void ListAllUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ListAllUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a list of all open user accounts on the console
|
* @brief This returns a list of all open user accounts on the console
|
||||||
*/
|
*/
|
||||||
void ListOpenUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ListOpenUsers(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the user ID of the last active user on the console
|
* @brief This returns the user ID of the last active user on the console
|
||||||
*/
|
*/
|
||||||
void GetLastOpenedUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetLastOpenedUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This provides information about the running application for account services to use (https://switchbrew.org/wiki/Account_services#InitializeApplicationInfoV0)
|
* @brief This provides information about the running application for account services to use (https://switchbrew.org/wiki/Account_services#InitializeApplicationInfoV0)
|
||||||
*/
|
*/
|
||||||
void InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a handle to an IProfile which can be used for reading user information
|
* @brief This returns a handle to an IProfile which can be used for reading user information
|
||||||
*/
|
*/
|
||||||
void GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a handle to an IManagerForApplication which can be used for reading Nintendo Online info
|
* @brief This returns a handle to an IManagerForApplication which can be used for reading Nintendo Online info
|
||||||
*/
|
*/
|
||||||
void GetBaasAccountManagerForApplication(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetBaasAccountManagerForApplication(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ namespace skyline::service::account {
|
|||||||
{0x1, SFUNC(IProfile::GetBase)}
|
{0x1, SFUNC(IProfile::GetBase)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IProfile::Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IProfile::Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct AccountUserData {
|
struct AccountUserData {
|
||||||
u32 _unk0_;
|
u32 _unk0_;
|
||||||
u32 iconID; //!< Icon ID (0 = Mii, the rest are character icon IDs)
|
u32 iconID; //!< Icon ID (0 = Mii, the rest are character icon IDs)
|
||||||
@ -23,10 +23,10 @@ namespace skyline::service::account {
|
|||||||
auto userData = state.process->GetPointer<AccountUserData>(request.outputBuf.at(0).address);
|
auto userData = state.process->GetPointer<AccountUserData>(request.outputBuf.at(0).address);
|
||||||
userData->iconBackgroundColorID = 0x1; // Color indexing starts at 0x1
|
userData->iconBackgroundColorID = 0x1; // Color indexing starts at 0x1
|
||||||
|
|
||||||
GetBase(session, request, response);
|
return GetBase(session, request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IProfile::GetBase(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IProfile::GetBase(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct {
|
struct {
|
||||||
UserId uid; //!< The UID of the corresponding account
|
UserId uid; //!< The UID of the corresponding account
|
||||||
u64 lastEditTimestamp; //!< A POSIX UTC timestamp denoting the last account edit
|
u64 lastEditTimestamp; //!< A POSIX UTC timestamp denoting the last account edit
|
||||||
@ -40,5 +40,7 @@ namespace skyline::service::account {
|
|||||||
std::memcpy(accountProfileBase.nickname.data(), username.c_str(), usernameSize);
|
std::memcpy(accountProfileBase.nickname.data(), username.c_str(), usernameSize);
|
||||||
|
|
||||||
response.Push(accountProfileBase);
|
response.Push(accountProfileBase);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,11 @@ namespace skyline::service::account {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns AccountUserData and AccountProfileBase objects that describe the user's information
|
* @brief This returns AccountUserData and AccountProfileBase objects that describe the user's information
|
||||||
*/
|
*/
|
||||||
void Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns an AccountProfileBase object that describe the user's information
|
* @brief This returns an AccountProfileBase object that describe the user's information
|
||||||
*/
|
*/
|
||||||
void GetBase(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetBase(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,19 +16,23 @@ namespace skyline::service::am {
|
|||||||
{0x15E, SFUNC(IAllSystemAppletProxiesService::OpenApplicationProxy)}
|
{0x15E, SFUNC(IAllSystemAppletProxiesService::OpenApplicationProxy)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IAllSystemAppletProxiesService::OpenLibraryAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ILibraryAppletProxy), session, response);
|
manager.RegisterService(SRVREG(ILibraryAppletProxy), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAllSystemAppletProxiesService::OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAllSystemAppletProxiesService::OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IApplicationProxy), session, response);
|
manager.RegisterService(SRVREG(IApplicationProxy), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAllSystemAppletProxiesService::OpenOverlayAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAllSystemAppletProxiesService::OpenOverlayAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IOverlayAppletProxy), session, response);
|
manager.RegisterService(SRVREG(IOverlayAppletProxy), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAllSystemAppletProxiesService::OpenSystemAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ISystemAppletProxy), session, response);
|
manager.RegisterService(SRVREG(ISystemAppletProxy), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,21 +17,21 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns #ILibraryAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenLibraryAppletProxy)
|
* @brief This returns #ILibraryAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenLibraryAppletProxy)
|
||||||
*/
|
*/
|
||||||
void OpenLibraryAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenLibraryAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #IApplicationProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy)
|
* @brief This returns #IApplicationProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy)
|
||||||
*/
|
*/
|
||||||
void OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #IOverlayAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenOverlayAppletProxy)
|
* @brief This returns #IOverlayAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenOverlayAppletProxy)
|
||||||
*/
|
*/
|
||||||
void OpenOverlayAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenOverlayAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #ISystemAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenSystemAppletProxy)
|
* @brief This returns #ISystemAppletProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenSystemAppletProxy)
|
||||||
*/
|
*/
|
||||||
void OpenSystemAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenSystemAppletProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ namespace skyline::service::am {
|
|||||||
{0x0, SFUNC(IApplicationProxyService::OpenApplicationProxy)}
|
{0x0, SFUNC(IApplicationProxyService::OpenApplicationProxy)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IApplicationProxyService::OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationProxyService::OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IApplicationProxy), session, response);
|
manager.RegisterService(SRVREG(IApplicationProxy), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns #IApplicationProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy)
|
* @brief This returns #IApplicationProxy (https://switchbrew.org/wiki/Applet_Manager_services#OpenApplicationProxy)
|
||||||
*/
|
*/
|
||||||
void OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenApplicationProxy(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -15,22 +15,29 @@ namespace skyline::service::am {
|
|||||||
{0x65, SFUNC(ILibraryAppletAccessor::PopOutData)},
|
{0x65, SFUNC(ILibraryAppletAccessor::PopOutData)},
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ILibraryAppletAccessor::GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
stateChangeEvent->Signal();
|
stateChangeEvent->Signal();
|
||||||
|
|
||||||
KHandle handle = state.process->InsertItem(stateChangeEvent);
|
KHandle handle = state.process->InsertItem(stateChangeEvent);
|
||||||
state.logger->Debug("Applet State Change Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Applet State Change Event Handle: 0x{:X}", handle);
|
||||||
|
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ILibraryAppletAccessor::Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ILibraryAppletAccessor::GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PushInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ILibraryAppletAccessor::PushInData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result 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 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
|
constexpr size_t LaunchParameterSize = 0x88; //!< This is the size of the launch parameter IStorage
|
||||||
|
|
||||||
@ -41,5 +48,6 @@ namespace skyline::service::am {
|
|||||||
storageService->Push(constant::DefaultUserId);
|
storageService->Push(constant::DefaultUserId);
|
||||||
|
|
||||||
manager.RegisterService(storageService, session, response);
|
manager.RegisterService(storageService, session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,26 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This function returns a handle to the library applet state change event
|
* @brief This function returns a handle to the library applet state change event
|
||||||
*/
|
*/
|
||||||
void GetAppletStateChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result 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)
|
* @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);
|
Result 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)
|
* @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);
|
Result 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)
|
* @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);
|
Result 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)
|
* @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);
|
Result PopOutData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace skyline::service::am {
|
|||||||
{0x82, SFUNC(IApplicationFunctions::GetGpuErrorDetectedSystemEvent)},
|
{0x82, SFUNC(IApplicationFunctions::GetGpuErrorDetectedSystemEvent)},
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IApplicationFunctions::PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationFunctions::PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
constexpr u32 LaunchParameterMagic = 0xC79497CA; //!< This is the magic of the application launch parameters
|
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
|
constexpr size_t LaunchParameterSize = 0x88; //!< This is the size of the launch parameter IStorage
|
||||||
|
|
||||||
@ -30,32 +30,42 @@ namespace skyline::service::am {
|
|||||||
storageService->Push(constant::DefaultUserId);
|
storageService->Push(constant::DefaultUserId);
|
||||||
|
|
||||||
manager.RegisterService(storageService, session, response);
|
manager.RegisterService(storageService, session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::EnsureSaveData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationFunctions::EnsureSaveData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u8>(0);
|
response.Push<u8>(0);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationFunctions::GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(util::MakeMagic<u64>("en-US"));
|
response.Push(util::MakeMagic<u64>("en-US"));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationFunctions::NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u8>(1);
|
response.Push<u8>(1);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationFunctions::GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u64>(0L);
|
response.Push<u64>(0L);
|
||||||
response.Push<u64>(0L);
|
response.Push<u64>(0L);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::InitializeGamePlayRecording(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IApplicationFunctions::InitializeGamePlayRecording(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::SetGamePlayRecordingState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IApplicationFunctions::SetGamePlayRecordingState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationFunctions::GetGpuErrorDetectedSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle = state.process->InsertItem(gpuErrorEvent);
|
auto handle = state.process->InsertItem(gpuErrorEvent);
|
||||||
state.logger->Debug("GPU Error Event Handle: 0x{:X}", handle);
|
state.logger->Debug("GPU Error Event Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,41 +21,41 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns an Applet Manager IStorage containing the application's launch parameters (https://switchbrew.org/wiki/Applet_Manager_services#PopLaunchParameter)
|
* @brief This returns an Applet Manager IStorage containing the application's launch parameters (https://switchbrew.org/wiki/Applet_Manager_services#PopLaunchParameter)
|
||||||
*/
|
*/
|
||||||
void PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This creates a save data folder for the requesting application (https://switchbrew.org/wiki/Applet_Manager_services#EnsureSaveData)
|
* @brief This creates a save data folder for the requesting application (https://switchbrew.org/wiki/Applet_Manager_services#EnsureSaveData)
|
||||||
*/
|
*/
|
||||||
void EnsureSaveData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result EnsureSaveData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the desired language for the application (https://switchbrew.org/wiki/Applet_Manager_services#GetDesiredLanguage)
|
* @brief This returns the desired language for the application (https://switchbrew.org/wiki/Applet_Manager_services#GetDesiredLanguage)
|
||||||
*/
|
*/
|
||||||
void GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns if the application is running or not, always returns true (https://switchbrew.org/wiki/Applet_Manager_services#NotifyRunning)
|
* @brief This returns if the application is running or not, always returns true (https://switchbrew.org/wiki/Applet_Manager_services#NotifyRunning)
|
||||||
*/
|
*/
|
||||||
void NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a UUID, however what it refers to is currently unknown (https://switchbrew.org/wiki/Applet_Manager_services#GetPseudoDeviceId)
|
* @brief This returns a UUID, however what it refers to is currently unknown (https://switchbrew.org/wiki/Applet_Manager_services#GetPseudoDeviceId)
|
||||||
*/
|
*/
|
||||||
void GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This initializes gameplay recording (https://switchbrew.org/wiki/Applet_Manager_services#InitializeGamePlayRecording)
|
* @brief This initializes gameplay recording (https://switchbrew.org/wiki/Applet_Manager_services#InitializeGamePlayRecording)
|
||||||
*/
|
*/
|
||||||
void InitializeGamePlayRecording(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result InitializeGamePlayRecording(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This controls the gameplay recording state (https://switchbrew.org/wiki/Applet_Manager_services#SetGamePlayRecordingState)
|
* @brief This controls the gameplay recording state (https://switchbrew.org/wiki/Applet_Manager_services#SetGamePlayRecordingState)
|
||||||
*/
|
*/
|
||||||
void SetGamePlayRecordingState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetGamePlayRecordingState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This obtains a handle to the system GPU error KEvent (https://switchbrew.org/wiki/Applet_Manager_services#GetGpuErrorDetectedSystemEvent)
|
* @brief This obtains a handle to the system GPU error KEvent (https://switchbrew.org/wiki/Applet_Manager_services#GetGpuErrorDetectedSystemEvent)
|
||||||
*/
|
*/
|
||||||
void GetGpuErrorDetectedSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetGpuErrorDetectedSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,19 @@ namespace skyline::service::am {
|
|||||||
{0x2, SFUNC(IAudioController::GetLibraryAppletExpectedMasterVolume)}
|
{0x2, SFUNC(IAudioController::GetLibraryAppletExpectedMasterVolume)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IAudioController::SetExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioController::SetExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
mainAppletVolume = request.Pop<float>();
|
mainAppletVolume = request.Pop<float>();
|
||||||
libraryAppletVolume = request.Pop<float>();
|
libraryAppletVolume = request.Pop<float>();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioController::GetMainAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioController::GetMainAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<float>(mainAppletVolume);
|
response.Push<float>(mainAppletVolume);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioController::GetLibraryAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioController::GetLibraryAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<float>(libraryAppletVolume);
|
response.Push<float>(libraryAppletVolume);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,16 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This sets the expected volumes for an application (https://switchbrew.org/wiki/Applet_Manager_services#SetExpectedMasterVolume)
|
* @brief This sets the expected volumes for an application (https://switchbrew.org/wiki/Applet_Manager_services#SetExpectedMasterVolume)
|
||||||
*/
|
*/
|
||||||
void SetExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the main applet volume that is expected by the application (https://switchbrew.org/wiki/Applet_Manager_services#GetMainAppletExpectedMasterVolume)
|
* @brief This returns the main applet volume that is expected by the application (https://switchbrew.org/wiki/Applet_Manager_services#GetMainAppletExpectedMasterVolume)
|
||||||
*/
|
*/
|
||||||
void GetMainAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetMainAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the library applet volume that is expected by the application (https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletExpectedMasterVolume)
|
* @brief This returns the library applet volume that is expected by the application (https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletExpectedMasterVolume)
|
||||||
*/
|
*/
|
||||||
void GetLibraryAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetLibraryAppletExpectedMasterVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -23,35 +23,38 @@ namespace skyline::service::am {
|
|||||||
QueueMessage(Message::FocusStateChange);
|
QueueMessage(Message::FocusStateChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ICommonStateGetter::GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle = state.process->InsertItem(messageEvent);
|
auto handle = state.process->InsertItem(messageEvent);
|
||||||
state.logger->Debug("Applet Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Applet Event Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::ReceiveMessage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ICommonStateGetter::ReceiveMessage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
if (messageQueue.empty()) {
|
if (messageQueue.empty())
|
||||||
response.errorCode = constant::status::NoMessages;
|
return result::NoMessages;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
response.Push(messageQueue.front());
|
response.Push(messageQueue.front());
|
||||||
messageQueue.pop();
|
messageQueue.pop();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ICommonStateGetter::GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(focusState);
|
response.Push(focusState);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ICommonStateGetter::GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(operationMode);
|
response.Push(operationMode);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ICommonStateGetter::GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(static_cast<u32>(operationMode));
|
response.Push(static_cast<u32>(operationMode));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetDefaultDisplayResolution(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ICommonStateGetter::GetDefaultDisplayResolution(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
if (operationMode == OperationMode::Handheld) {
|
if (operationMode == OperationMode::Handheld) {
|
||||||
response.Push<u32>(constant::HandheldResolutionW);
|
response.Push<u32>(constant::HandheldResolutionW);
|
||||||
response.Push<u32>(constant::HandheldResolutionH);
|
response.Push<u32>(constant::HandheldResolutionH);
|
||||||
@ -59,5 +62,6 @@ namespace skyline::service::am {
|
|||||||
response.Push<u32>(constant::DockedResolutionW);
|
response.Push<u32>(constant::DockedResolutionW);
|
||||||
response.Push<u32>(constant::DockedResolutionH);
|
response.Push<u32>(constant::DockedResolutionH);
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
#include <services/serviceman.h>
|
#include <services/serviceman.h>
|
||||||
|
|
||||||
namespace skyline::service::am {
|
namespace skyline::service::am {
|
||||||
|
namespace result {
|
||||||
|
constexpr Result NoMessages(128, 3);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief https://switchbrew.org/wiki/Applet_Manager_services#ICommonStateGetter
|
* @brief https://switchbrew.org/wiki/Applet_Manager_services#ICommonStateGetter
|
||||||
*/
|
*/
|
||||||
@ -53,31 +57,31 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns the handle to a KEvent object that is signalled whenever RecieveMessage has a message (https://switchbrew.org/wiki/Applet_Manager_services#GetEventHandle)
|
* @brief This returns the handle to a KEvent object that is signalled whenever RecieveMessage has a message (https://switchbrew.org/wiki/Applet_Manager_services#GetEventHandle)
|
||||||
*/
|
*/
|
||||||
void GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns an #AppletMessage or 0x680 to indicate the lack of a message (https://switchbrew.org/wiki/Applet_Manager_services#ReceiveMessage)
|
* @brief This returns an #AppletMessage or 0x680 to indicate the lack of a message (https://switchbrew.org/wiki/Applet_Manager_services#ReceiveMessage)
|
||||||
*/
|
*/
|
||||||
void ReceiveMessage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ReceiveMessage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns if an application is in focus or not. It always returns in focus on the emulator (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState)
|
* @brief This returns if an application is in focus or not. It always returns in focus on the emulator (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState)
|
||||||
*/
|
*/
|
||||||
void GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the current OperationMode (https://switchbrew.org/wiki/Applet_Manager_services#GetOperationMode)
|
* @brief This returns the current OperationMode (https://switchbrew.org/wiki/Applet_Manager_services#GetOperationMode)
|
||||||
*/
|
*/
|
||||||
void GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the current PerformanceMode (Same as operationMode but u32) (https://switchbrew.org/wiki/Applet_Manager_services#GetPerformanceMode)
|
* @brief This returns the current PerformanceMode (Same as operationMode but u32) (https://switchbrew.org/wiki/Applet_Manager_services#GetPerformanceMode)
|
||||||
*/
|
*/
|
||||||
void GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the current display width and height in two u32s (https://switchbrew.org/wiki/Applet_Manager_services#GetDefaultDisplayResolution)
|
* @brief This returns the current display width and height in two u32s (https://switchbrew.org/wiki/Applet_Manager_services#GetDefaultDisplayResolution)
|
||||||
*/
|
*/
|
||||||
void GetDefaultDisplayResolution(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetDefaultDisplayResolution(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,16 +11,18 @@ namespace skyline::service::am {
|
|||||||
{0xA, SFUNC(ILibraryAppletCreator::CreateStorage)}
|
{0xA, SFUNC(ILibraryAppletCreator::CreateStorage)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ILibraryAppletCreator::CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ILibraryAppletCreator::CreateLibraryApplet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ILibraryAppletAccessor), session, response);
|
manager.RegisterService(SRVREG(ILibraryAppletAccessor), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletCreator::CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ILibraryAppletCreator::CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto size = request.Pop<i64>();
|
auto size = request.Pop<i64>();
|
||||||
|
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
throw exception("Cannot create an IStorage with a negative size");
|
throw exception("Cannot create an IStorage with a negative size");
|
||||||
|
|
||||||
manager.RegisterService(std::make_shared<IStorage>(state, manager, size), session, response);
|
manager.RegisterService(std::make_shared<IStorage>(state, manager, size), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This function returns a handle to a library applet accessor (https://switchbrew.org/wiki/Applet_Manager_services#CreateLibraryApplet)
|
* @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);
|
Result 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)
|
* @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);
|
Result CreateStorage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,30 +20,45 @@ namespace skyline::service::am {
|
|||||||
{0x5B, SFUNC(ISelfController::GetLibraryAppletLaunchableEvent)}
|
{0x5B, SFUNC(ISelfController::GetLibraryAppletLaunchableEvent)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ISelfController::LockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ISelfController::LockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ISelfController::UnlockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ISelfController::UnlockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ISelfController::GetLibraryAppletLaunchableEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISelfController::GetLibraryAppletLaunchableEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
libraryAppletLaunchableEvent->Signal();
|
libraryAppletLaunchableEvent->Signal();
|
||||||
|
|
||||||
KHandle handle = state.process->InsertItem(libraryAppletLaunchableEvent);
|
KHandle handle = state.process->InsertItem(libraryAppletLaunchableEvent);
|
||||||
state.logger->Debug("Library Applet Launchable Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Library Applet Launchable Event Handle: 0x{:X}", handle);
|
||||||
|
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ISelfController::SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ISelfController::SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ISelfController::SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ISelfController::SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ISelfController::SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ISelfController::SetRestartMessageEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ISelfController::SetRestartMessageEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ISelfController::SetOutOfFocusSuspendingEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ISelfController::SetOutOfFocusSuspendingEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ISelfController::CreateManagedDisplayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISelfController::CreateManagedDisplayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.logger->Debug("Creating Managed Layer on Default Display");
|
state.logger->Debug("Creating Managed Layer on Default Display");
|
||||||
|
|
||||||
auto hosBinder = state.os->serviceManager.GetService<hosbinder::IHOSBinderDriver>("dispdrv");
|
auto hosBinder = state.os->serviceManager.GetService<hosbinder::IHOSBinderDriver>("dispdrv");
|
||||||
@ -52,12 +67,14 @@ namespace skyline::service::am {
|
|||||||
hosBinder->layerStatus = hosbinder::LayerStatus::Managed;
|
hosBinder->layerStatus = hosbinder::LayerStatus::Managed;
|
||||||
|
|
||||||
response.Push<u64>(0);
|
response.Push<u64>(0);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::GetAccumulatedSuspendedTickChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISelfController::GetAccumulatedSuspendedTickChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle = state.process->InsertItem(accumulatedSuspendedTickChangedEvent);
|
auto handle = state.process->InsertItem(accumulatedSuspendedTickChangedEvent);
|
||||||
state.logger->Debug("Accumulated Suspended Tick Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Accumulated Suspended Tick Event Handle: 0x{:X}", handle);
|
||||||
|
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,51 +21,51 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This function prevents the running application from being quit via the home button (https://switchbrew.org/wiki/Applet_Manager_services#LockExit)
|
* @brief This function prevents the running application from being quit via the home button (https://switchbrew.org/wiki/Applet_Manager_services#LockExit)
|
||||||
*/
|
*/
|
||||||
void LockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result LockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function allows the running application to be quit via the home button (https://switchbrew.org/wiki/Applet_Manager_services#UnlockExit)
|
* @brief This function allows the running application to be quit via the home button (https://switchbrew.org/wiki/Applet_Manager_services#UnlockExit)
|
||||||
*/
|
*/
|
||||||
void UnlockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result UnlockExit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function obtains a handle to the library applet launchable event (https://switchbrew.org/wiki/Applet_Manager_services#GetLibraryAppletLaunchableEvent)
|
* @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);
|
Result 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)
|
* @brief This function takes a u8 bool flag and no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetOperationModeChangedNotification)
|
||||||
*/
|
*/
|
||||||
void SetOperationModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetOperationModeChangedNotification(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#SetPerformanceModeChangedNotification)
|
* @brief This function takes a u8 bool flag and no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetPerformanceModeChangedNotification)
|
||||||
*/
|
*/
|
||||||
void SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetPerformanceModeChangedNotification(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function takes 3 unknown u8 values and has no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState)
|
* @brief This function takes 3 unknown u8 values and has no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#GetCurrentFocusState)
|
||||||
*/
|
*/
|
||||||
void SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetFocusHandlingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function toggles whether a restart message should be sent (https://switchbrew.org/wiki/Applet_Manager_services#SetRestartMessageEnabled)
|
* @brief This function toggles whether a restart message should be sent (https://switchbrew.org/wiki/Applet_Manager_services#SetRestartMessageEnabled)
|
||||||
*/
|
*/
|
||||||
void SetRestartMessageEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetRestartMessageEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function takes a u8 bool flag and has no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetOutOfFocusSuspendingEnabled)
|
* @brief This function takes a u8 bool flag and has no output (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#SetOutOfFocusSuspendingEnabled)
|
||||||
*/
|
*/
|
||||||
void SetOutOfFocusSuspendingEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetOutOfFocusSuspendingEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function returns an output u64 LayerId (https://switchbrew.org/wiki/Applet_Manager_services#CreateManagedDisplayLayer)
|
* @brief This function returns an output u64 LayerId (https://switchbrew.org/wiki/Applet_Manager_services#CreateManagedDisplayLayer)
|
||||||
*/
|
*/
|
||||||
void CreateManagedDisplayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateManagedDisplayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This obtains a handle to the system sleep time change KEvent (https://switchbrew.org/wiki/Applet_Manager_services#GetAccumulatedSuspendedTickChangedEvent)
|
* @brief This obtains a handle to the system sleep time change KEvent (https://switchbrew.org/wiki/Applet_Manager_services#GetAccumulatedSuspendedTickChangedEvent)
|
||||||
*/
|
*/
|
||||||
void GetAccumulatedSuspendedTickChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAccumulatedSuspendedTickChangedEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,12 @@ namespace skyline::service::am {
|
|||||||
{0xA, SFUNC(IWindowController::AcquireForegroundRights)}
|
{0xA, SFUNC(IWindowController::AcquireForegroundRights)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IWindowController::GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IWindowController::GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(static_cast<u64>(state.process->pid));
|
response.Push(static_cast<u64>(state.process->pid));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWindowController::AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IWindowController::AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns the PID of the current application (https://switchbrew.org/wiki/Applet_Manager_services#GetAppletResourceUserId)
|
* @brief This returns the PID of the current application (https://switchbrew.org/wiki/Applet_Manager_services#GetAppletResourceUserId)
|
||||||
*/
|
*/
|
||||||
void GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function has mo inputs or outputs (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#AcquireForegroundRights)
|
* @brief This function has mo inputs or outputs (Stubbed) (https://switchbrew.org/wiki/Applet_Manager_services#AcquireForegroundRights)
|
||||||
*/
|
*/
|
||||||
void AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ namespace skyline::service::am {
|
|||||||
{0x3E8, SFUNC(BaseProxy::GetDebugFunctions)}
|
{0x3E8, SFUNC(BaseProxy::GetDebugFunctions)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IApplicationProxy::GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IApplicationProxy::GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IApplicationFunctions), session, response);
|
manager.RegisterService(SRVREG(IApplicationFunctions), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,6 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns #IApplicationFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions)
|
* @brief This returns #IApplicationFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IApplicationFunctions)
|
||||||
*/
|
*/
|
||||||
void GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,37 +12,45 @@
|
|||||||
#include "base_proxy.h"
|
#include "base_proxy.h"
|
||||||
|
|
||||||
namespace skyline::service::am {
|
namespace skyline::service::am {
|
||||||
BaseProxy::BaseProxy(const DeviceState &state, ServiceManager &manager, const std::unordered_map<u32, std::function<void(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)>> &vTable) : BaseService(state, manager, vTable) {}
|
BaseProxy::BaseProxy(const DeviceState &state, ServiceManager &manager, const std::unordered_map<u32, std::function<Result(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)>> &vTable) : BaseService(state, manager, vTable) {}
|
||||||
|
|
||||||
void BaseProxy::GetCommonStateGetter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetCommonStateGetter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ICommonStateGetter), session, response);
|
manager.RegisterService(SRVREG(ICommonStateGetter), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProxy::GetSelfController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetSelfController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ISelfController), session, response);
|
manager.RegisterService(SRVREG(ISelfController), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProxy::GetWindowController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetWindowController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IWindowController), session, response);
|
manager.RegisterService(SRVREG(IWindowController), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProxy::GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IAudioController), session, response);
|
manager.RegisterService(SRVREG(IAudioController), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProxy::GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IDisplayController), session, response);
|
manager.RegisterService(SRVREG(IDisplayController), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProxy::GetLibraryAppletCreator(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetLibraryAppletCreator(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ILibraryAppletCreator), session, response);
|
manager.RegisterService(SRVREG(ILibraryAppletCreator), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProxy::GetDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IDebugFunctions), session, response);
|
manager.RegisterService(SRVREG(IDebugFunctions), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseProxy::GetAppletCommonFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result BaseProxy::GetAppletCommonFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IAppletCommonFunctions), session, response);
|
manager.RegisterService(SRVREG(IAppletCommonFunctions), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,46 +12,46 @@ namespace skyline::service::am {
|
|||||||
*/
|
*/
|
||||||
class BaseProxy : public BaseService {
|
class BaseProxy : public BaseService {
|
||||||
public:
|
public:
|
||||||
BaseProxy(const DeviceState &state, ServiceManager &manager, const std::unordered_map<u32, std::function<void(type::KSession & , ipc::IpcRequest & , ipc::IpcResponse & )>> &vTable);
|
BaseProxy(const DeviceState &state, ServiceManager &manager, const std::unordered_map<u32, std::function<Result(type::KSession & , ipc::IpcRequest & , ipc::IpcResponse & )>> &vTable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #ICommonStateGetter (https://switchbrew.org/wiki/Applet_Manager_services#ICommonStateGetter)
|
* @brief This returns #ICommonStateGetter (https://switchbrew.org/wiki/Applet_Manager_services#ICommonStateGetter)
|
||||||
*/
|
*/
|
||||||
void GetCommonStateGetter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetCommonStateGetter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #ISelfController (https://switchbrew.org/wiki/Applet_Manager_services#ISelfController)
|
* @brief This returns #ISelfController (https://switchbrew.org/wiki/Applet_Manager_services#ISelfController)
|
||||||
*/
|
*/
|
||||||
void GetSelfController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSelfController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #IWindowController (https://switchbrew.org/wiki/Applet_Manager_services#IWindowController)
|
* @brief This returns #IWindowController (https://switchbrew.org/wiki/Applet_Manager_services#IWindowController)
|
||||||
*/
|
*/
|
||||||
void GetWindowController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetWindowController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #IAudioController (https://switchbrew.org/wiki/Applet_Manager_services#IAudioController)
|
* @brief This returns #IAudioController (https://switchbrew.org/wiki/Applet_Manager_services#IAudioController)
|
||||||
*/
|
*/
|
||||||
void GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAudioController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #IDisplayController (https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController)
|
* @brief This returns #IDisplayController (https://switchbrew.org/wiki/Applet_Manager_services#IDisplayController)
|
||||||
*/
|
*/
|
||||||
void GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetDisplayController(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #ILibraryAppletCreator (https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletCreator)
|
* @brief This returns #ILibraryAppletCreator (https://switchbrew.org/wiki/Applet_Manager_services#ILibraryAppletCreator)
|
||||||
*/
|
*/
|
||||||
void GetLibraryAppletCreator(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetLibraryAppletCreator(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #IDebugFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions)
|
* @brief This returns #IDebugFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IDebugFunctions)
|
||||||
*/
|
*/
|
||||||
void GetDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetDebugFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns #IAppletCommonFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IAppletCommonFunctions)
|
* @brief This returns #IAppletCommonFunctions (https://switchbrew.org/wiki/Applet_Manager_services#IAppletCommonFunctions)
|
||||||
*/
|
*/
|
||||||
void GetAppletCommonFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAppletCommonFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ namespace skyline::service::am {
|
|||||||
{0x0, SFUNC(IStorage::Open)}
|
{0x0, SFUNC(IStorage::Open)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IStorage::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
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, shared_from_this()), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns an IStorageAccessor that can read and write data to an IStorage
|
* @brief This returns an IStorageAccessor that can read and write data to an IStorage
|
||||||
*/
|
*/
|
||||||
void Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function writes an object to the storage
|
* @brief This function writes an object to the storage
|
||||||
|
@ -12,30 +12,34 @@ namespace skyline::service::am {
|
|||||||
{0xB, SFUNC(IStorageAccessor::Read)}
|
{0xB, SFUNC(IStorageAccessor::Read)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IStorageAccessor::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IStorageAccessor::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<i64>(parent->content.size());
|
response.Push<i64>(parent->content.size());
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IStorageAccessor::Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IStorageAccessor::Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto offset = request.Pop<i64>();
|
auto offset = request.Pop<i64>();
|
||||||
auto size = request.inputBuf.at(0).size;
|
auto size = std::min(static_cast<i64>(request.inputBuf.at(0).size), static_cast<i64>(parent->content.size()) - offset);
|
||||||
|
|
||||||
if (offset + size > parent->content.size())
|
if (offset > parent->content.size())
|
||||||
throw exception("Trying to write past the end of an IStorage");
|
return result::OutOfBounds;
|
||||||
|
|
||||||
if (offset < 0)
|
if (size > 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);
|
||||||
|
|
||||||
state.process->ReadMemory(parent->content.data() + offset, request.inputBuf.at(0).address, size);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IStorageAccessor::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto offset = request.Pop<u64>();
|
auto offset = request.Pop<i64>();
|
||||||
auto size = request.outputBuf.at(0).size;
|
auto size = std::min(static_cast<i64>(request.inputBuf.at(0).size), static_cast<i64>(parent->content.size()) - offset);
|
||||||
|
|
||||||
if (offset + size > parent->content.size())
|
if (offset > parent->content.size())
|
||||||
throw exception("Trying to read past the end of an IStorage");
|
return result::OutOfBounds;
|
||||||
|
|
||||||
state.process->WriteMemory(parent->content.data() + offset, request.outputBuf.at(0).address, size);
|
if (size > 0)
|
||||||
|
state.process->WriteMemory(parent->content.data() + offset, request.outputBuf.at(0).address, size);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#include <services/serviceman.h>
|
#include <services/serviceman.h>
|
||||||
|
|
||||||
namespace skyline::service::am {
|
namespace skyline::service::am {
|
||||||
|
namespace result {
|
||||||
|
constexpr Result OutOfBounds(128, 503);
|
||||||
|
}
|
||||||
class IStorage;
|
class IStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,16 +25,16 @@ namespace skyline::service::am {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns the size of the storage in bytes
|
* @brief This returns the size of the storage in bytes
|
||||||
*/
|
*/
|
||||||
void GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This writes a buffer to the storage at the specified offset
|
* @brief This writes a buffer to the storage at the specified offset
|
||||||
*/
|
*/
|
||||||
void Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result 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
|
* @brief This returns a buffer containing the contents of the storage at the specified offset
|
||||||
*/
|
*/
|
||||||
void Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ namespace skyline::service::apm {
|
|||||||
{0x0, SFUNC(IManager::OpenSession)}
|
{0x0, SFUNC(IManager::OpenSession)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IManager::OpenSession(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IManager::OpenSession(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ISession), session, response);
|
manager.RegisterService(SRVREG(ISession), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::apm {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns an handle to ISession
|
* @brief This returns an handle to ISession
|
||||||
*/
|
*/
|
||||||
void OpenSession(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenSession(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,17 @@ namespace skyline::service::apm {
|
|||||||
{0x1, SFUNC(ISession::GetPerformanceConfiguration)}
|
{0x1, SFUNC(ISession::GetPerformanceConfiguration)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ISession::SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISession::SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto mode = request.Pop<u32>();
|
auto mode = request.Pop<u32>();
|
||||||
auto config = request.Pop<u32>();
|
auto config = request.Pop<u32>();
|
||||||
performanceConfig.at(mode) = config;
|
performanceConfig.at(mode) = config;
|
||||||
state.logger->Info("SetPerformanceConfiguration called with 0x{:X} ({})", config, mode ? "Docked" : "Handheld");
|
state.logger->Info("SetPerformanceConfiguration called with 0x{:X} ({})", config, mode ? "Docked" : "Handheld");
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISession::GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISession::GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
u32 performanceMode = request.Pop<u32>();
|
auto performanceMode = request.Pop<u32>();
|
||||||
response.Push<u32>(performanceConfig.at(performanceMode));
|
response.Push<u32>(performanceConfig.at(performanceMode));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@ namespace skyline::service::apm {
|
|||||||
/**
|
/**
|
||||||
* @brief This sets performanceConfig to the given arguments, it doesn't affect anything else (https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration)
|
* @brief This sets performanceConfig to the given arguments, it doesn't affect anything else (https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration)
|
||||||
*/
|
*/
|
||||||
void SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This retrieves the particular performanceConfig for a mode and returns it to the client (https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration)
|
* @brief This retrieves the particular performanceConfig for a mode and returns it to the client (https://switchbrew.org/wiki/PPC_services#SetPerformanceConfiguration)
|
||||||
*/
|
*/
|
||||||
void GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace skyline::service::audio {
|
|||||||
{0xA, SFUNC(IAudioDevice::GetActiveAudioDeviceName)}
|
{0xA, SFUNC(IAudioDevice::GetActiveAudioDeviceName)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IAudioDevice::ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioDevice::ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
u64 offset{};
|
u64 offset{};
|
||||||
for (std::string deviceName : {"AudioTvOutput", "AudioStereoJackOutput", "AudioBuiltInSpeakerOutput"}) {
|
for (std::string deviceName : {"AudioTvOutput", "AudioStereoJackOutput", "AudioBuiltInSpeakerOutput"}) {
|
||||||
if (offset + deviceName.size() + 1 > request.outputBuf.at(0).size)
|
if (offset + deviceName.size() + 1 > request.outputBuf.at(0).size)
|
||||||
@ -26,26 +26,32 @@ namespace skyline::service::audio {
|
|||||||
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address + offset, deviceName.size() + 1);
|
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address + offset, deviceName.size() + 1);
|
||||||
offset += deviceName.size() + 1;
|
offset += deviceName.size() + 1;
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioDevice::SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IAudioDevice::SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void IAudioDevice::GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioDevice::GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
std::string deviceName("AudioStereoJackOutput");
|
std::string deviceName("AudioStereoJackOutput");
|
||||||
|
|
||||||
if (deviceName.size() > request.outputBuf.at(0).size)
|
if (deviceName.size() > request.outputBuf.at(0).size)
|
||||||
throw exception("Too small a buffer supplied to GetActiveAudioDeviceName");
|
throw exception("Too small a buffer supplied to GetActiveAudioDeviceName");
|
||||||
|
|
||||||
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address, deviceName.size() + 1);
|
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address, deviceName.size() + 1);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioDevice::QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioDevice::QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle{state.process->InsertItem(systemEvent)};
|
auto handle{state.process->InsertItem(systemEvent)};
|
||||||
state.logger->Debug("Audio Device System Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Audio Device System Event Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioDevice::GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioDevice::GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u32>(constant::ChannelCount);
|
response.Push<u32>(constant::ChannelCount);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,26 +20,26 @@ namespace skyline::service::audio {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns a list of the available audio devices (https://switchbrew.org/wiki/Audio_services#ListAudioDeviceName)
|
* @brief This returns a list of the available audio devices (https://switchbrew.org/wiki/Audio_services#ListAudioDeviceName)
|
||||||
*/
|
*/
|
||||||
void ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the volume of an audio output (https://switchbrew.org/wiki/Audio_services#SetAudioDeviceOutputVolume)
|
* @brief This sets the volume of an audio output (https://switchbrew.org/wiki/Audio_services#SetAudioDeviceOutputVolume)
|
||||||
*/
|
*/
|
||||||
void SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the active audio output device
|
* @brief This returns the active audio output device
|
||||||
*/
|
*/
|
||||||
void GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the audio device system event
|
* @brief This returns the audio device system event
|
||||||
*/
|
*/
|
||||||
void QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the current output devices channel count
|
* @brief This returns the current output devices channel count
|
||||||
*/
|
*/
|
||||||
void GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -23,21 +23,24 @@ namespace skyline::service::audio {
|
|||||||
state.audio->CloseTrack(track);
|
state.audio->CloseTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOut::GetAudioOutState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOut::GetAudioOutState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(static_cast<u32>(track->playbackState));
|
response.Push(static_cast<u32>(track->playbackState));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOut::StartAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOut::StartAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.logger->Debug("IAudioOut: Start playback");
|
state.logger->Debug("IAudioOut: Start playback");
|
||||||
track->Start();
|
track->Start();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOut::StopAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOut::StopAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.logger->Debug("IAudioOut: Stop playback");
|
state.logger->Debug("IAudioOut: Stop playback");
|
||||||
track->Stop();
|
track->Stop();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOut::AppendAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOut::AppendAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u64 nextBufferPtr;
|
u64 nextBufferPtr;
|
||||||
u64 sampleBufferPtr;
|
u64 sampleBufferPtr;
|
||||||
@ -55,15 +58,18 @@ namespace skyline::service::audio {
|
|||||||
} else {
|
} else {
|
||||||
track->AppendBuffer(tag, std::span(state.process->GetPointer<i16>(data.sampleBufferPtr), data.sampleSize / sizeof(i16)));
|
track->AppendBuffer(tag, std::span(state.process->GetPointer<i16>(data.sampleBufferPtr), data.sampleSize / sizeof(i16)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOut::RegisterBufferEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOut::RegisterBufferEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle{state.process->InsertItem(releaseEvent)};
|
auto handle{state.process->InsertItem(releaseEvent)};
|
||||||
state.logger->Debug("IAudioOut: Buffer Release Event Handle: 0x{:X}", handle);
|
state.logger->Debug("IAudioOut: Buffer Release Event Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOut::GetReleasedAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOut::GetReleasedAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto maxCount{static_cast<u32>(request.outputBuf.at(0).size >> 3)};
|
auto maxCount{static_cast<u32>(request.outputBuf.at(0).size >> 3)};
|
||||||
std::vector<u64> releasedBuffers{track->GetReleasedBuffers(maxCount)};
|
std::vector<u64> releasedBuffers{track->GetReleasedBuffers(maxCount)};
|
||||||
auto count{static_cast<u32>(releasedBuffers.size())};
|
auto count{static_cast<u32>(releasedBuffers.size())};
|
||||||
@ -73,11 +79,13 @@ namespace skyline::service::audio {
|
|||||||
state.process->WriteMemory(releasedBuffers.data(), request.outputBuf.at(0).address, request.outputBuf.at(0).size);
|
state.process->WriteMemory(releasedBuffers.data(), request.outputBuf.at(0).address, request.outputBuf.at(0).size);
|
||||||
|
|
||||||
response.Push<u32>(count);
|
response.Push<u32>(count);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOut::ContainsAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOut::ContainsAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto tag{request.Pop<u64>()};
|
auto tag{request.Pop<u64>()};
|
||||||
|
|
||||||
response.Push(static_cast<u32>(track->ContainsBuffer(tag)));
|
response.Push(static_cast<u32>(track->ContainsBuffer(tag)));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,36 +37,36 @@ namespace skyline::service::audio {
|
|||||||
/**
|
/**
|
||||||
* @brief Returns the playback state of the audio output (https://switchbrew.org/wiki/Audio_services#GetAudioOutState)
|
* @brief Returns the playback state of the audio output (https://switchbrew.org/wiki/Audio_services#GetAudioOutState)
|
||||||
*/
|
*/
|
||||||
void GetAudioOutState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAudioOutState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Starts playback using data from appended samples (https://switchbrew.org/wiki/Audio_services#StartAudioOut)
|
* @brief Starts playback using data from appended samples (https://switchbrew.org/wiki/Audio_services#StartAudioOut)
|
||||||
*/
|
*/
|
||||||
void StartAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result StartAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stops playback of audio, waits for all samples to be released (https://switchbrew.org/wiki/Audio_services#StartAudioOut)
|
* @brief Stops playback of audio, waits for all samples to be released (https://switchbrew.org/wiki/Audio_services#StartAudioOut)
|
||||||
*/
|
*/
|
||||||
void StopAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result StopAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Appends sample data to the output buffer (https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer)
|
* @brief Appends sample data to the output buffer (https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer)
|
||||||
*/
|
*/
|
||||||
void AppendAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result AppendAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a handle to the sample release KEvent (https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer)
|
* @brief Returns a handle to the sample release KEvent (https://switchbrew.org/wiki/Audio_services#AppendAudioOutBuffer)
|
||||||
*/
|
*/
|
||||||
void RegisterBufferEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result RegisterBufferEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the IDs of all pending released buffers (https://switchbrew.org/wiki/Audio_services#GetReleasedAudioOutBuffer)
|
* @brief Returns the IDs of all pending released buffers (https://switchbrew.org/wiki/Audio_services#GetReleasedAudioOutBuffer)
|
||||||
*/
|
*/
|
||||||
void GetReleasedAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetReleasedAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if the given buffer ID is in the playback queue (https://switchbrew.org/wiki/Audio_services#ContainsAudioOutBuffer)
|
* @brief Checks if the given buffer ID is in the playback queue (https://switchbrew.org/wiki/Audio_services#ContainsAudioOutBuffer)
|
||||||
*/
|
*/
|
||||||
void ContainsAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ContainsAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,12 @@ namespace skyline::service::audio {
|
|||||||
{0x3, SFUNC(IAudioOutManager::OpenAudioOut)}
|
{0x3, SFUNC(IAudioOutManager::OpenAudioOut)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IAudioOutManager::ListAudioOuts(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOutManager::ListAudioOuts(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.process->WriteMemory(reinterpret_cast<void *>(const_cast<char *>(constant::DefaultAudioOutName.data())), request.outputBuf.at(0).address, constant::DefaultAudioOutName.size());
|
state.process->WriteMemory(reinterpret_cast<void *>(const_cast<char *>(constant::DefaultAudioOutName.data())), request.outputBuf.at(0).address, constant::DefaultAudioOutName.size());
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioOutManager::OpenAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioOutManager::OpenAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto sampleRate{request.Pop<u32>()};
|
auto sampleRate{request.Pop<u32>()};
|
||||||
auto channelCount{static_cast<u16>(request.Pop<u32>())};
|
auto channelCount{static_cast<u16>(request.Pop<u32>())};
|
||||||
|
|
||||||
@ -32,5 +33,7 @@ namespace skyline::service::audio {
|
|||||||
response.Push<u16>(0);
|
response.Push<u16>(0);
|
||||||
response.Push(static_cast<u32>(skyline::audio::AudioFormat::Int16));
|
response.Push(static_cast<u32>(skyline::audio::AudioFormat::Int16));
|
||||||
response.Push(static_cast<u32>(skyline::audio::AudioOutState::Stopped));
|
response.Push(static_cast<u32>(skyline::audio::AudioOutState::Stopped));
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,12 @@ namespace skyline {
|
|||||||
/**
|
/**
|
||||||
* @brief Returns a list of all available audio outputs (https://switchbrew.org/wiki/Audio_services#ListAudioOuts)
|
* @brief Returns a list of all available audio outputs (https://switchbrew.org/wiki/Audio_services#ListAudioOuts)
|
||||||
*/
|
*/
|
||||||
void ListAudioOuts(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ListAudioOuts(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new audoutU::IAudioOut object and returns a handle to it (https://switchbrew.org/wiki/Audio_services#OpenAudioOut)
|
* @brief Creates a new audoutU::IAudioOut object and returns a handle to it (https://switchbrew.org/wiki/Audio_services#OpenAudioOut)
|
||||||
*/
|
*/
|
||||||
void OpenAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenAudioOut(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,23 +34,27 @@ namespace skyline::service::audio::IAudioRenderer {
|
|||||||
state.audio->CloseTrack(track);
|
state.audio->CloseTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::GetSampleRate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::GetSampleRate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u32>(parameters.sampleRate);
|
response.Push<u32>(parameters.sampleRate);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::GetSampleCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::GetSampleCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u32>(parameters.sampleCount);
|
response.Push<u32>(parameters.sampleCount);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::GetMixBufferCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::GetMixBufferCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u32>(parameters.subMixCount);
|
response.Push<u32>(parameters.subMixCount);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::GetState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::GetState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(static_cast<u32>(playbackState));
|
response.Push(static_cast<u32>(playbackState));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::RequestUpdate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::RequestUpdate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto inputAddress{request.inputBuf.at(0).address};
|
auto inputAddress{request.inputBuf.at(0).address};
|
||||||
|
|
||||||
auto inputHeader{state.process->GetObject<UpdateDataHeader>(inputAddress)};
|
auto inputHeader{state.process->GetObject<UpdateDataHeader>(inputAddress)};
|
||||||
@ -125,6 +129,8 @@ namespace skyline::service::audio::IAudioRenderer {
|
|||||||
state.process->WriteMemory(effect.output, outputAddress);
|
state.process->WriteMemory(effect.output, outputAddress);
|
||||||
outputAddress += sizeof(EffectOut);
|
outputAddress += sizeof(EffectOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::UpdateAudio() {
|
void IAudioRenderer::UpdateAudio() {
|
||||||
@ -171,17 +177,20 @@ namespace skyline::service::audio::IAudioRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
playbackState = skyline::audio::AudioOutState::Started;
|
playbackState = skyline::audio::AudioOutState::Started;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::Stop(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::Stop(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
playbackState = skyline::audio::AudioOutState::Stopped;
|
playbackState = skyline::audio::AudioOutState::Stopped;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRenderer::QuerySystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRenderer::QuerySystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle{state.process->InsertItem(systemEvent)};
|
auto handle{state.process->InsertItem(systemEvent)};
|
||||||
state.logger->Debug("Audren System Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Audren System Event Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,42 +98,42 @@ namespace skyline {
|
|||||||
/**
|
/**
|
||||||
* @brief Returns the sample rate (https://switchbrew.org/wiki/Audio_services#GetSampleRate)
|
* @brief Returns the sample rate (https://switchbrew.org/wiki/Audio_services#GetSampleRate)
|
||||||
*/
|
*/
|
||||||
void GetSampleRate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSampleRate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the sample count (https://switchbrew.org/wiki/Audio_services#GetSampleCount)
|
* @brief Returns the sample count (https://switchbrew.org/wiki/Audio_services#GetSampleCount)
|
||||||
*/
|
*/
|
||||||
void GetSampleCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSampleCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the number of mix buffers (https://switchbrew.org/wiki/Audio_services#GetMixBufferCount)
|
* @brief Returns the number of mix buffers (https://switchbrew.org/wiki/Audio_services#GetMixBufferCount)
|
||||||
*/
|
*/
|
||||||
void GetMixBufferCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetMixBufferCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the state of the renderer (https://switchbrew.org/wiki/Audio_services#GetAudioRendererState) (stubbed)?
|
* @brief Returns the state of the renderer (https://switchbrew.org/wiki/Audio_services#GetAudioRendererState) (stubbed)?
|
||||||
*/
|
*/
|
||||||
void GetState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the audio renderer state and appends new data to playback buffers
|
* @brief Updates the audio renderer state and appends new data to playback buffers
|
||||||
*/
|
*/
|
||||||
void RequestUpdate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result RequestUpdate(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start the audio stream from the renderer
|
* @brief Start the audio stream from the renderer
|
||||||
*/
|
*/
|
||||||
void Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Start(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop the audio stream from the renderer
|
* @brief Stop the audio stream from the renderer
|
||||||
*/
|
*/
|
||||||
void Stop(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Stop(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a handle to the sample release KEvent
|
* @brief Returns a handle to the sample release KEvent
|
||||||
*/
|
*/
|
||||||
void QuerySystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result QuerySystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,15 +14,17 @@ namespace skyline::service::audio {
|
|||||||
{0x4, SFUNC(IAudioRendererManager::GetAudioDeviceService)}
|
{0x4, SFUNC(IAudioRendererManager::GetAudioDeviceService)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IAudioRendererManager::OpenAudioRenderer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRendererManager::OpenAudioRenderer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
IAudioRenderer::AudioRendererParameters params = request.Pop<IAudioRenderer::AudioRendererParameters>();
|
IAudioRenderer::AudioRendererParameters params = request.Pop<IAudioRenderer::AudioRendererParameters>();
|
||||||
|
|
||||||
state.logger->Debug("IAudioRendererManager: Opening a rev {} IAudioRenderer with sample rate: {}, voice count: {}, effect count: {}", IAudioRenderer::ExtractVersionFromRevision(params.revision), params.sampleRate, params.voiceCount, params.effectCount);
|
state.logger->Debug("IAudioRendererManager: Opening a rev {} IAudioRenderer with sample rate: {}, voice count: {}, effect count: {}", IAudioRenderer::ExtractVersionFromRevision(params.revision), params.sampleRate, params.voiceCount, params.effectCount);
|
||||||
|
|
||||||
manager.RegisterService(std::make_shared<IAudioRenderer::IAudioRenderer>(state, manager, params), session, response);
|
manager.RegisterService(std::make_shared<IAudioRenderer::IAudioRenderer>(state, manager, params), session, response);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRendererManager::GetAudioRendererWorkBufferSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRendererManager::GetAudioRendererWorkBufferSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
IAudioRenderer::AudioRendererParameters params = request.Pop<IAudioRenderer::AudioRendererParameters>();
|
IAudioRenderer::AudioRendererParameters params = request.Pop<IAudioRenderer::AudioRendererParameters>();
|
||||||
|
|
||||||
IAudioRenderer::RevisionInfo revisionInfo{};
|
IAudioRenderer::RevisionInfo revisionInfo{};
|
||||||
@ -86,9 +88,11 @@ namespace skyline::service::audio {
|
|||||||
|
|
||||||
state.logger->Debug("IAudioRendererManager: Work buffer size: 0x{:X}", size);
|
state.logger->Debug("IAudioRendererManager: Work buffer size: 0x{:X}", size);
|
||||||
response.Push<i64>(size);
|
response.Push<i64>(size);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAudioRendererManager::GetAudioDeviceService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAudioRendererManager::GetAudioDeviceService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IAudioDevice), session, response);
|
manager.RegisterService(SRVREG(IAudioDevice), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,16 +17,16 @@ namespace skyline::service::audio {
|
|||||||
/**
|
/**
|
||||||
* @brief Creates a new IAudioRenderer object and returns a handle to it
|
* @brief Creates a new IAudioRenderer object and returns a handle to it
|
||||||
*/
|
*/
|
||||||
void OpenAudioRenderer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenAudioRenderer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculates the size of the buffer the guest needs to allocate for IAudioRendererManager
|
* @brief Calculates the size of the buffer the guest needs to allocate for IAudioRendererManager
|
||||||
*/
|
*/
|
||||||
void GetAudioRendererWorkBufferSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAudioRendererWorkBufferSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a handle to an instance of an IAudioDevice (https://switchbrew.org/wiki/Audio_services#GetAudioDeviceService)
|
* @brief This returns a handle to an instance of an IAudioDevice (https://switchbrew.org/wiki/Audio_services#GetAudioDeviceService)
|
||||||
*/
|
*/
|
||||||
void GetAudioDeviceService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAudioDeviceService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,14 @@ namespace skyline::service {
|
|||||||
protected:
|
protected:
|
||||||
const DeviceState &state; //!< The state of the device
|
const DeviceState &state; //!< The state of the device
|
||||||
ServiceManager &manager; //!< A reference to the service manager
|
ServiceManager &manager; //!< A reference to the service manager
|
||||||
std::unordered_map<u32, std::function<void(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)>> vTable; //!< This holds the mapping from a function's CmdId to the actual function
|
std::unordered_map<u32, std::function<Result(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)>> vTable; //!< This holds the mapping from a function's CmdId to the actual function
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @param state The state of the device
|
* @param state The state of the device
|
||||||
* @param vTable The functions of the service
|
* @param vTable The functions of the service
|
||||||
*/
|
*/
|
||||||
BaseService(const DeviceState &state, ServiceManager &manager, const std::unordered_map<u32, std::function<void(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)>> &vTable) : state(state), manager(manager), vTable(vTable) {}
|
BaseService(const DeviceState &state, ServiceManager &manager, const std::unordered_map<u32, std::function<Result(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)>> &vTable) : state(state), manager(manager), vTable(vTable) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @note To be able to extract the name of the underlying class and ensure correct destruction order
|
* @note To be able to extract the name of the underlying class and ensure correct destruction order
|
||||||
@ -57,17 +57,17 @@ namespace skyline::service {
|
|||||||
* @param request The corresponding IpcRequest object
|
* @param request The corresponding IpcRequest object
|
||||||
* @param response The corresponding IpcResponse object
|
* @param response The corresponding IpcResponse object
|
||||||
*/
|
*/
|
||||||
void HandleRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result HandleRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
std::function<void(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)> function;
|
std::function<Result(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &)> function;
|
||||||
try {
|
try {
|
||||||
function = vTable.at(request.payload->value);
|
function = vTable.at(request.payload->value);
|
||||||
} catch (std::out_of_range &) {
|
} catch (std::out_of_range &) {
|
||||||
state.logger->Warn("Cannot find function in service '{0}': 0x{1:X} ({1})", GetName(), static_cast<u32>(request.payload->value));
|
state.logger->Warn("Cannot find function in service '{0}': 0x{1:X} ({1})", GetName(), static_cast<u32>(request.payload->value));
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
function(session, request, response);
|
return function(session, request, response);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
throw exception("{} (Service: {})", e.what(), GetName());
|
throw exception("{} (Service: {})", e.what(), GetName());
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ namespace skyline::service::fatalsrv {
|
|||||||
{0x2, SFUNC(IService::ThrowFatal)}
|
{0x2, SFUNC(IService::ThrowFatal)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IService::ThrowFatal(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IService::ThrowFatal(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
throw exception("A fatal error with code: 0x{:X} has caused emulation to stop", request.Pop<u32>());
|
throw exception("A fatal error with code: 0x{:X} has caused emulation to stop", request.Pop<u32>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::fatalsrv {
|
|||||||
/**
|
/**
|
||||||
* @brief This throws an exception that causes emulation to quit
|
* @brief This throws an exception that causes emulation to quit
|
||||||
*/
|
*/
|
||||||
void ThrowFatal(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ThrowFatal(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ namespace skyline::service::friends {
|
|||||||
{0x0, SFUNC(INotificationService::GetEvent)},
|
{0x0, SFUNC(INotificationService::GetEvent)},
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void INotificationService::GetEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INotificationService::GetEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
KHandle handle = state.process->InsertItem(notificationEvent);
|
KHandle handle = state.process->InsertItem(notificationEvent);
|
||||||
state.logger->Debug("Friend Notification Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Friend Notification Event Handle: 0x{:X}", handle);
|
||||||
|
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,6 @@ namespace skyline::service::friends {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns a handle to the notification event
|
* @brief This returns a handle to the notification event
|
||||||
*/
|
*/
|
||||||
void GetEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,13 @@ namespace skyline::service::friends {
|
|||||||
{0x1, SFUNC(IServiceCreator::CreateNotificationService)},
|
{0x1, SFUNC(IServiceCreator::CreateNotificationService)},
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IServiceCreator::CreateFriendService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IServiceCreator::CreateFriendService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IFriendService), session, response);
|
manager.RegisterService(SRVREG(IFriendService), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IServiceCreator::CreateNotificationService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IServiceCreator::CreateNotificationService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(INotificationService), session, response);
|
manager.RegisterService(SRVREG(INotificationService), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@ namespace skyline::service::friends {
|
|||||||
/**
|
/**
|
||||||
* @brief This opens an IFriendService that can be used by applications to access user friend info
|
* @brief This opens an IFriendService that can be used by applications to access user friend info
|
||||||
*/
|
*/
|
||||||
void CreateFriendService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateFriendService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This opens an INotificationService that can be used by applications to receive notifications
|
* @brief This opens an INotificationService that can be used by applications to receive notifications
|
||||||
*/
|
*/
|
||||||
void CreateNotificationService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateNotificationService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
#include <kernel/types/KProcess.h>
|
#include <kernel/types/KProcess.h>
|
||||||
|
#include "results.h"
|
||||||
#include "IFile.h"
|
#include "IFile.h"
|
||||||
|
|
||||||
namespace skyline::service::fssrv {
|
namespace skyline::service::fssrv {
|
||||||
@ -13,7 +14,7 @@ namespace skyline::service::fssrv {
|
|||||||
{0x4, SFUNC(IFile::GetSize)}
|
{0x4, SFUNC(IFile::GetSize)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IFile::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFile::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto readOption = request.Pop<u32>();
|
auto readOption = request.Pop<u32>();
|
||||||
request.Skip<u32>();
|
request.Skip<u32>();
|
||||||
auto offset = request.Pop<i64>();
|
auto offset = request.Pop<i64>();
|
||||||
@ -21,20 +22,19 @@ namespace skyline::service::fssrv {
|
|||||||
|
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
state.logger->Warn("Trying to read a file with a negative offset");
|
state.logger->Warn("Trying to read a file with a negative offset");
|
||||||
response.errorCode = constant::status::InvAddress;
|
return result::InvalidOffset;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
state.logger->Warn("Trying to read a file with a negative size");
|
state.logger->Warn("Trying to read a file with a negative size");
|
||||||
response.errorCode = constant::status::InvSize;
|
return result::InvalidSize;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Push<u32>(static_cast<u32>(backing->Read(state.process->GetPointer<u8>(request.outputBuf.at(0).address), offset, size)));
|
response.Push<u32>(static_cast<u32>(backing->Read(state.process->GetPointer<u8>(request.outputBuf.at(0).address), offset, size)));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFile::Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFile::Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto writeOption = request.Pop<u32>();
|
auto writeOption = request.Pop<u32>();
|
||||||
request.Skip<u32>();
|
request.Skip<u32>();
|
||||||
auto offset = request.Pop<i64>();
|
auto offset = request.Pop<i64>();
|
||||||
@ -42,35 +42,38 @@ namespace skyline::service::fssrv {
|
|||||||
|
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
state.logger->Warn("Trying to write to a file with a negative offset");
|
state.logger->Warn("Trying to write to a file with a negative offset");
|
||||||
response.errorCode = constant::status::InvAddress;
|
return result::InvalidOffset;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
state.logger->Warn("Trying to write to a file with a negative size");
|
state.logger->Warn("Trying to write to a file with a negative size");
|
||||||
response.errorCode = constant::status::InvSize;
|
return result::InvalidSize;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.inputBuf.at(0).size < size) {
|
if (request.inputBuf.at(0).size < size) {
|
||||||
state.logger->Warn("The input buffer is not large enough to fit the requested size");
|
state.logger->Warn("The input buffer is not large enough to fit the requested size");
|
||||||
response.errorCode = constant::status::InvSize;
|
return result::InvalidSize;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backing->Write(state.process->GetPointer<u8>(request.inputBuf.at(0).address), offset, request.inputBuf.at(0).size) != size) {
|
if (backing->Write(state.process->GetPointer<u8>(request.inputBuf.at(0).address), offset, request.inputBuf.at(0).size) != size) {
|
||||||
state.logger->Warn("Failed to write all data to the backing");
|
state.logger->Warn("Failed to write all data to the backing");
|
||||||
response.errorCode = constant::status::GenericError;
|
return result::UnexpectedFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFile::Flush(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IFile::Flush(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void IFile::SetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFile::SetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
backing->Resize(request.Pop<u64>());
|
backing->Resize(request.Pop<u64>());
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFile::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFile::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u64>(backing->size);
|
response.Push<u64>(backing->size);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,26 @@ namespace skyline::service::fssrv {
|
|||||||
/**
|
/**
|
||||||
* @brief This reads a buffer from a region of an IFile
|
* @brief This reads a buffer from a region of an IFile
|
||||||
*/
|
*/
|
||||||
void Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This writes a buffer to a region of an IFile
|
* @brief This writes a buffer to a region of an IFile
|
||||||
*/
|
*/
|
||||||
void Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Write(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This flushes any written data to the IFile on the Switch, however the emulator processes any FS event immediately so this does nothing
|
* @brief This flushes any written data to the IFile on the Switch, however the emulator processes any FS event immediately so this does nothing
|
||||||
*/
|
*/
|
||||||
void Flush(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Flush(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the size of an IFile
|
* @brief This sets the size of an IFile
|
||||||
*/
|
*/
|
||||||
void SetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This obtains the size of an IFile
|
* @brief This obtains the size of an IFile
|
||||||
*/
|
*/
|
||||||
void GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <kernel/types/KProcess.h>
|
#include <kernel/types/KProcess.h>
|
||||||
#include <vfs/filesystem.h>
|
#include <vfs/filesystem.h>
|
||||||
|
#include "results.h"
|
||||||
#include "IFile.h"
|
#include "IFile.h"
|
||||||
#include "IFileSystem.h"
|
#include "IFileSystem.h"
|
||||||
|
|
||||||
@ -14,42 +15,45 @@ namespace skyline::service::fssrv {
|
|||||||
{0xA, SFUNC(IFileSystem::Commit)}
|
{0xA, SFUNC(IFileSystem::Commit)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IFileSystem::CreateFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystem::CreateFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
std::string path = std::string(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
std::string path = std::string(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
||||||
auto mode = request.Pop<u64>();
|
auto mode = request.Pop<u64>();
|
||||||
auto size = request.Pop<u32>();
|
auto size = request.Pop<u32>();
|
||||||
|
|
||||||
response.errorCode = backing->CreateFile(path, size) ? constant::status::Success : constant::status::PathDoesNotExist;
|
return backing->CreateFile(path, size) ? Result{} : result::PathDoesNotExist;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystem::GetEntryType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystem::GetEntryType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
std::string path = std::string(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
std::string path = std::string(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
||||||
|
|
||||||
auto type = backing->GetEntryType(path);
|
auto type = backing->GetEntryType(path);
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
response.Push(*type);
|
response.Push(*type);
|
||||||
|
return {};
|
||||||
} else {
|
} else {
|
||||||
response.Push<u32>(0);
|
response.Push<u32>(0);
|
||||||
response.errorCode = constant::status::PathDoesNotExist;
|
return result::PathDoesNotExist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystem::OpenFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystem::OpenFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
std::string path = std::string(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
std::string path(state.process->GetPointer<char>(request.inputBuf.at(0).address));
|
||||||
auto mode = request.Pop<vfs::Backing::Mode>();
|
auto mode = request.Pop<vfs::Backing::Mode>();
|
||||||
|
|
||||||
if (!backing->FileExists(path)) {
|
if (!backing->FileExists(path))
|
||||||
response.errorCode = constant::status::PathDoesNotExist;
|
return result::PathDoesNotExist;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto file = backing->OpenFile(path, mode);
|
auto file = backing->OpenFile(path, mode);
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
response.errorCode = constant::status::GenericError;
|
return result::UnexpectedFailure;
|
||||||
else
|
else
|
||||||
manager.RegisterService(std::make_shared<IFile>(file, state, manager), session, response);
|
manager.RegisterService(std::make_shared<IFile>(file, state, manager), session, response);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystem::Commit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IFileSystem::Commit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,21 +21,21 @@ namespace skyline::service::fssrv {
|
|||||||
/**
|
/**
|
||||||
* @brief This creates a file at the specified path in the filesystem
|
* @brief This creates a file at the specified path in the filesystem
|
||||||
*/
|
*/
|
||||||
void CreateFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This queries the DirectoryEntryType of the given path (https://switchbrew.org/wiki/Filesystem_services#GetEntryType)
|
* @brief This queries the DirectoryEntryType of the given path (https://switchbrew.org/wiki/Filesystem_services#GetEntryType)
|
||||||
*/
|
*/
|
||||||
void GetEntryType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetEntryType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns an IFile handle for the requested path (https://switchbrew.org/wiki/Filesystem_services#OpenFile)
|
* @brief This returns an IFile handle for the requested path (https://switchbrew.org/wiki/Filesystem_services#OpenFile)
|
||||||
*/
|
*/
|
||||||
void OpenFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenFile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This commits all changes to the filesystem (https://switchbrew.org/wiki/Filesystem_services#Commit)
|
* @brief This commits all changes to the filesystem (https://switchbrew.org/wiki/Filesystem_services#Commit)
|
||||||
*/
|
*/
|
||||||
void Commit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Commit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
#include <os.h>
|
#include <os.h>
|
||||||
#include <vfs/os_filesystem.h>
|
#include <vfs/os_filesystem.h>
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
#include "IFileSystemProxy.h"
|
#include "results.h"
|
||||||
#include "IStorage.h"
|
#include "IStorage.h"
|
||||||
|
#include "IFileSystemProxy.h"
|
||||||
|
|
||||||
namespace skyline::service::fssrv {
|
namespace skyline::service::fssrv {
|
||||||
IFileSystemProxy::IFileSystemProxy(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, {
|
IFileSystemProxy::IFileSystemProxy(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, {
|
||||||
@ -16,15 +17,17 @@ namespace skyline::service::fssrv {
|
|||||||
{0x3ED, SFUNC(IFileSystemProxy::GetGlobalAccessLogMode)},
|
{0x3ED, SFUNC(IFileSystemProxy::GetGlobalAccessLogMode)},
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IFileSystemProxy::SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystemProxy::SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
process = request.Pop<pid_t>();
|
process = request.Pop<pid_t>();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystemProxy::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystemProxy::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(std::make_shared<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->appFilesPath + "/switch/sdmc/"), state, manager), session, response);
|
manager.RegisterService(std::make_shared<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->appFilesPath + "/switch/sdmc/"), state, manager), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystemProxy::OpenSaveDataFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystemProxy::OpenSaveDataFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto spaceId = request.Pop<SaveDataSpaceId>();
|
auto spaceId = request.Pop<SaveDataSpaceId>();
|
||||||
auto attribute = request.Pop<SaveDataAttribute>();
|
auto attribute = request.Pop<SaveDataAttribute>();
|
||||||
|
|
||||||
@ -61,16 +64,20 @@ namespace skyline::service::fssrv {
|
|||||||
}();
|
}();
|
||||||
|
|
||||||
manager.RegisterService(std::make_shared<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->appFilesPath + "/switch" + saveDataPath), state, manager), session, response);
|
manager.RegisterService(std::make_shared<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->appFilesPath + "/switch" + saveDataPath), state, manager), session, response);
|
||||||
|
return {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystemProxy::OpenDataStorageByCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystemProxy::OpenDataStorageByCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
if (state.loader->romFs)
|
if (!state.loader->romFs)
|
||||||
manager.RegisterService(std::make_shared<IStorage>(state.loader->romFs, state, manager), session, response);
|
return result::NoRomFsAvailable;
|
||||||
else
|
|
||||||
throw exception("Tried to call OpenDataStorageByCurrentProcess without a valid RomFS");
|
manager.RegisterService(std::make_shared<IStorage>(state.loader->romFs, state, manager), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystemProxy::GetGlobalAccessLogMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IFileSystemProxy::GetGlobalAccessLogMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u32>(0);
|
response.Push<u32>(0);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,26 +68,26 @@ namespace skyline::service::fssrv {
|
|||||||
/**
|
/**
|
||||||
* @brief This sets the PID of the process using FS currently (https://switchbrew.org/wiki/Filesystem_services#SetCurrentProcess)
|
* @brief This sets the PID of the process using FS currently (https://switchbrew.org/wiki/Filesystem_services#SetCurrentProcess)
|
||||||
*/
|
*/
|
||||||
void SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a handle to an instance of #IFileSystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) with type SDCard
|
* @brief This returns a handle to an instance of #IFileSystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) with type SDCard
|
||||||
*/
|
*/
|
||||||
void OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a handle to an instance of #IFileSystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) for the requested save data area
|
* @brief This returns a handle to an instance of #IFileSystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) for the requested save data area
|
||||||
*/
|
*/
|
||||||
void OpenSaveDataFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenSaveDataFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a handle to an instance of #IStorage (https://switchbrew.org/wiki/Filesystem_services#IStorage) for the application's data storage
|
* @brief This returns a handle to an instance of #IStorage (https://switchbrew.org/wiki/Filesystem_services#IStorage) for the application's data storage
|
||||||
*/
|
*/
|
||||||
void OpenDataStorageByCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenDataStorageByCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the filesystem log access mode (https://switchbrew.org/wiki/Filesystem_services#GetGlobalAccessLogMode)
|
* @brief This returns the filesystem log access mode (https://switchbrew.org/wiki/Filesystem_services#GetGlobalAccessLogMode)
|
||||||
*/
|
*/
|
||||||
void GetGlobalAccessLogMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetGlobalAccessLogMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
#include <kernel/types/KProcess.h>
|
#include <kernel/types/KProcess.h>
|
||||||
|
#include "results.h"
|
||||||
#include "IStorage.h"
|
#include "IStorage.h"
|
||||||
|
|
||||||
namespace skyline::service::fssrv {
|
namespace skyline::service::fssrv {
|
||||||
@ -10,26 +11,26 @@ namespace skyline::service::fssrv {
|
|||||||
{0x4, SFUNC(IStorage::GetSize)}
|
{0x4, SFUNC(IStorage::GetSize)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IStorage::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IStorage::Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto offset = request.Pop<i64>();
|
auto offset = request.Pop<i64>();
|
||||||
auto size = request.Pop<i64>();
|
auto size = request.Pop<i64>();
|
||||||
|
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
state.logger->Warn("Trying to read a file with a negative offset");
|
state.logger->Warn("Trying to read a file with a negative offset");
|
||||||
response.errorCode = constant::status::InvAddress;
|
return result::InvalidOffset;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
state.logger->Warn("Trying to read a file with a negative size");
|
state.logger->Warn("Trying to read a file with a negative size");
|
||||||
response.errorCode = constant::status::InvSize;
|
return result::InvalidSize;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backing->Read(state.process->GetPointer<u8>(request.outputBuf.at(0).address), offset, size);
|
backing->Read(state.process->GetPointer<u8>(request.outputBuf.at(0).address), offset, size);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IStorage::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IStorage::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u64>(backing->size);
|
response.Push<u64>(backing->size);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,11 @@ namespace skyline::service::fssrv {
|
|||||||
/**
|
/**
|
||||||
* @brief This reads a buffer from a region of an IStorage (https://switchbrew.org/wiki/Filesystem_services#Read)
|
* @brief This reads a buffer from a region of an IStorage (https://switchbrew.org/wiki/Filesystem_services#Read)
|
||||||
*/
|
*/
|
||||||
void Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Read(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This obtains the size of an IStorage (https://switchbrew.org/wiki/Filesystem_services#GetSize)
|
* @brief This obtains the size of an IStorage (https://switchbrew.org/wiki/Filesystem_services#GetSize)
|
||||||
*/
|
*/
|
||||||
void GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
15
app/src/main/cpp/skyline/services/fssrv/results.h
Normal file
15
app/src/main/cpp/skyline/services/fssrv/results.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
namespace skyline::service::fssrv::result {
|
||||||
|
constexpr Result PathDoesNotExist(2, 1);
|
||||||
|
constexpr Result NoRomFsAvailable(2, 1001);
|
||||||
|
constexpr Result UnexpectedFailure(2, 5000);
|
||||||
|
constexpr Result InvalidArgument(2, 6001);
|
||||||
|
constexpr Result InvalidOffset(2, 6061);
|
||||||
|
constexpr Result InvalidSize(2, 6062);
|
||||||
|
}
|
@ -11,10 +11,12 @@ namespace skyline::service::hid {
|
|||||||
{0x0, SFUNC(IActiveVibrationDeviceList::ActivateVibrationDevice)}
|
{0x0, SFUNC(IActiveVibrationDeviceList::ActivateVibrationDevice)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IActiveVibrationDeviceList::ActivateVibrationDevice(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IActiveVibrationDeviceList::ActivateVibrationDevice(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle = request.Pop<NpadDeviceHandle>();
|
auto handle = request.Pop<NpadDeviceHandle>();
|
||||||
|
|
||||||
if (!handle.isRight)
|
if (!handle.isRight)
|
||||||
state.input->npad.at(handle.id).vibrationRight = NpadVibrationValue{};
|
state.input->npad.at(handle.id).vibrationRight = NpadVibrationValue{};
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,6 @@ namespace skyline::service::hid {
|
|||||||
/**
|
/**
|
||||||
* @brief Activates a vibration device with the specified #VibrationDeviceHandle (https://switchbrew.org/wiki/HID_services#ActivateVibrationDevice)
|
* @brief Activates a vibration device with the specified #VibrationDeviceHandle (https://switchbrew.org/wiki/HID_services#ActivateVibrationDevice)
|
||||||
*/
|
*/
|
||||||
void ActivateVibrationDevice(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ActivateVibrationDevice(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ namespace skyline::service::hid {
|
|||||||
{0x0, SFUNC(IAppletResource::GetSharedMemoryHandle)}
|
{0x0, SFUNC(IAppletResource::GetSharedMemoryHandle)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IAppletResource::GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IAppletResource::GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle = state.process->InsertItem<type::KSharedMemory>(state.input->kHid);
|
auto handle = state.process->InsertItem<type::KSharedMemory>(state.input->kHid);
|
||||||
state.logger->Debug("HID Shared Memory Handle: 0x{:X}", handle);
|
state.logger->Debug("HID Shared Memory Handle: 0x{:X}", handle);
|
||||||
|
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,6 @@ namespace skyline::service::hid {
|
|||||||
/**
|
/**
|
||||||
* @brief This opens a handle to HID shared memory (https://switchbrew.org/wiki/HID_services#GetSharedMemoryHandle)
|
* @brief This opens a handle to HID shared memory (https://switchbrew.org/wiki/HID_services#GetSharedMemoryHandle)
|
||||||
*/
|
*/
|
||||||
void GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,12 @@ namespace skyline::service::hid {
|
|||||||
{0xCE, SFUNC(IHidServer::SendVibrationValues)}
|
{0xCE, SFUNC(IHidServer::SendVibrationValues)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IHidServer::CreateAppletResource(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::CreateAppletResource(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IAppletResource), session, response);
|
manager.RegisterService(SRVREG(IAppletResource), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto styleSet = request.Pop<NpadStyleSet>();
|
auto styleSet = request.Pop<NpadStyleSet>();
|
||||||
std::lock_guard lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.styles = styleSet;
|
state.input->npad.styles = styleSet;
|
||||||
@ -38,13 +39,15 @@ namespace skyline::service::hid {
|
|||||||
|
|
||||||
state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast<bool>(styleSet.proController), static_cast<bool>(styleSet.joyconHandheld), static_cast<bool>(styleSet.joyconDual), static_cast<bool>(styleSet.joyconLeft), static_cast<bool>
|
state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast<bool>(styleSet.proController), static_cast<bool>(styleSet.joyconHandheld), static_cast<bool>(styleSet.joyconDual), static_cast<bool>(styleSet.joyconLeft), static_cast<bool>
|
||||||
(styleSet.joyconRight), static_cast<bool>(styleSet.gamecube), static_cast<bool>(styleSet.palma), static_cast<bool>(styleSet.nes), static_cast<bool>(styleSet.nesHandheld), static_cast<bool>(styleSet.snes));
|
(styleSet.joyconRight), static_cast<bool>(styleSet.gamecube), static_cast<bool>(styleSet.palma), static_cast<bool>(styleSet.nes), static_cast<bool>(styleSet.nesHandheld), static_cast<bool>(styleSet.snes));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::GetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::GetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(state.input->npad.styles);
|
response.Push(state.input->npad.styles);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
const auto &buffer = request.inputBuf.at(0);
|
const auto &buffer = request.inputBuf.at(0);
|
||||||
u64 address = buffer.address;
|
u64 address = buffer.address;
|
||||||
size_t size = buffer.size / sizeof(NpadId);
|
size_t size = buffer.size / sizeof(NpadId);
|
||||||
@ -58,62 +61,73 @@ namespace skyline::service::hid {
|
|||||||
std::lock_guard lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.supportedIds = supportedIds;
|
state.input->npad.supportedIds = supportedIds;
|
||||||
state.input->npad.Update();
|
state.input->npad.Update();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.input->npad.Activate();
|
state.input->npad.Activate();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::DeactivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::DeactivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.input->npad.Deactivate();
|
state.input->npad.Deactivate();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::AcquireNpadStyleSetUpdateEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::AcquireNpadStyleSetUpdateEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
request.copyHandles.push_back(state.process->InsertItem(state.input->npad.at(id).updateEvent));
|
request.copyHandles.push_back(state.process->InsertItem(state.input->npad.at(id).updateEvent));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::ActivateNpadWithRevision(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::ActivateNpadWithRevision(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.input->npad.Activate();
|
state.input->npad.Activate();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
std::lock_guard lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
request.Skip<u64>();
|
request.Skip<u64>();
|
||||||
state.input->npad.orientation = request.Pop<NpadJoyOrientation>();
|
state.input->npad.orientation = request.Pop<NpadJoyOrientation>();
|
||||||
state.input->npad.Update();
|
state.input->npad.Update();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(state.input->npad.orientation);
|
response.Push(state.input->npad.orientation);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
std::lock_guard lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
||||||
state.input->npad.Update();
|
state.input->npad.Update();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
std::lock_guard lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
||||||
state.input->npad.Update();
|
state.input->npad.Update();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
std::lock_guard lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Dual);
|
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Dual);
|
||||||
state.input->npad.Update();
|
state.input->npad.Update();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::CreateActiveVibrationDeviceList(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::CreateActiveVibrationDeviceList(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IActiveVibrationDeviceList), session, response);
|
manager.RegisterService(SRVREG(IActiveVibrationDeviceList), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SendVibrationValues(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHidServer::SendVibrationValues(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
request.Skip<u64>(); // appletResourceUserId
|
request.Skip<u64>(); // appletResourceUserId
|
||||||
|
|
||||||
auto &handleBuf = request.inputBuf.at(0);
|
auto &handleBuf = request.inputBuf.at(0);
|
||||||
@ -136,5 +150,7 @@ namespace skyline::service::hid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,76 +18,76 @@ namespace skyline::service::hid {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns an IAppletResource (https://switchbrew.org/wiki/HID_services#CreateAppletResource)
|
* @brief This returns an IAppletResource (https://switchbrew.org/wiki/HID_services#CreateAppletResource)
|
||||||
*/
|
*/
|
||||||
void CreateAppletResource(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateAppletResource(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the style of controllers supported (https://switchbrew.org/wiki/HID_services#SetSupportedNpadStyleSet)
|
* @brief This sets the style of controllers supported (https://switchbrew.org/wiki/HID_services#SetSupportedNpadStyleSet)
|
||||||
*/
|
*/
|
||||||
void SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This gets the style of controllers supported (https://switchbrew.org/wiki/HID_services#GetSupportedNpadStyleSet)
|
* @brief This gets the style of controllers supported (https://switchbrew.org/wiki/HID_services#GetSupportedNpadStyleSet)
|
||||||
*/
|
*/
|
||||||
void GetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the NpadIds which are supported (https://switchbrew.org/wiki/HID_services#SetSupportedNpadIdType)
|
* @brief This sets the NpadIds which are supported (https://switchbrew.org/wiki/HID_services#SetSupportedNpadIdType)
|
||||||
*/
|
*/
|
||||||
void SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This requests the activation of controllers (https://switchbrew.org/wiki/HID_services#ActivateNpad)
|
* @brief This requests the activation of controllers (https://switchbrew.org/wiki/HID_services#ActivateNpad)
|
||||||
*/
|
*/
|
||||||
void ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This requests the deactivation of controllers (https://switchbrew.org/wiki/HID_services#DeactivateNpad)
|
* @brief This requests the deactivation of controllers (https://switchbrew.org/wiki/HID_services#DeactivateNpad)
|
||||||
*/
|
*/
|
||||||
void DeactivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result DeactivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This requests an event that's signalled on a specific NpadId changing (https://switchbrew.org/wiki/HID_services#AcquireNpadStyleSetUpdateEventHandle)
|
* @brief This requests an event that's signalled on a specific NpadId changing (https://switchbrew.org/wiki/HID_services#AcquireNpadStyleSetUpdateEventHandle)
|
||||||
*/
|
*/
|
||||||
void AcquireNpadStyleSetUpdateEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result AcquireNpadStyleSetUpdateEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This requests the activation of controllers with a specific HID revision (https://switchbrew.org/wiki/HID_services#ActivateNpadWithRevision)
|
* @brief This requests the activation of controllers with a specific HID revision (https://switchbrew.org/wiki/HID_services#ActivateNpadWithRevision)
|
||||||
*/
|
*/
|
||||||
void ActivateNpadWithRevision(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result ActivateNpadWithRevision(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the Joy-Con hold mode (https://switchbrew.org/wiki/HID_services#SetNpadJoyHoldType)
|
* @brief Sets the Joy-Con hold mode (https://switchbrew.org/wiki/HID_services#SetNpadJoyHoldType)
|
||||||
*/
|
*/
|
||||||
void SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the Joy-Con hold mode (https://switchbrew.org/wiki/HID_services#GetNpadJoyHoldType)
|
* @brief Sets the Joy-Con hold mode (https://switchbrew.org/wiki/HID_services#GetNpadJoyHoldType)
|
||||||
*/
|
*/
|
||||||
void GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the Joy-Con assignment mode to Single by default (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeSingleByDefault)
|
* @brief Sets the Joy-Con assignment mode to Single by default (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeSingleByDefault)
|
||||||
*/
|
*/
|
||||||
void SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the Joy-Con assignment mode to Single (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeSingle)
|
* @brief Sets the Joy-Con assignment mode to Single (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeSingle)
|
||||||
*/
|
*/
|
||||||
void SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the Joy-Con assignment mode to Dual (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeDual)
|
* @brief Sets the Joy-Con assignment mode to Dual (https://switchbrew.org/wiki/HID_services#SetNpadJoyAssignmentModeDual)
|
||||||
*/
|
*/
|
||||||
void SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns an instance of #IActiveVibrationDeviceList (https://switchbrew.org/wiki/HID_services#CreateActiveVibrationDeviceList)
|
* @brief Returns an instance of #IActiveVibrationDeviceList (https://switchbrew.org/wiki/HID_services#CreateActiveVibrationDeviceList)
|
||||||
*/
|
*/
|
||||||
void CreateActiveVibrationDeviceList(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateActiveVibrationDeviceList(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send vibration values to an NPad (https://switchbrew.org/wiki/HID_services#SendVibrationValues)
|
* @brief Send vibration values to an NPad (https://switchbrew.org/wiki/HID_services#SendVibrationValues)
|
||||||
*/
|
*/
|
||||||
void SendVibrationValues(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SendVibrationValues(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ namespace skyline::service::hosbinder {
|
|||||||
gbpBuffer->nvmapHandle, gbpBuffer->offset, (1U << gbpBuffer->blockHeightLog2), gbpBuffer->size);
|
gbpBuffer->nvmapHandle, gbpBuffer->offset, (1U << gbpBuffer->blockHeightLog2), gbpBuffer->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHOSBinderDriver::TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHOSBinderDriver::TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto layerId = request.Pop<u32>();
|
auto layerId = request.Pop<u32>();
|
||||||
auto code = request.Pop<TransactionCode>();
|
auto code = request.Pop<TransactionCode>();
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ namespace skyline::service::hosbinder {
|
|||||||
.height = constant::HandheldResolutionH,
|
.height = constant::HandheldResolutionH,
|
||||||
.transformHint = 0,
|
.transformHint = 0,
|
||||||
.pendingBuffers = 0,
|
.pendingBuffers = 0,
|
||||||
.status = constant::status::Success,
|
.status = 0,
|
||||||
};
|
};
|
||||||
out.WriteData(connect);
|
out.WriteData(connect);
|
||||||
break;
|
break;
|
||||||
@ -207,20 +207,24 @@ namespace skyline::service::hosbinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.WriteParcel(request.outputBuf.at(0));
|
out.WriteParcel(request.outputBuf.at(0));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHOSBinderDriver::AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHOSBinderDriver::AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
request.Skip<u32>();
|
request.Skip<u32>();
|
||||||
auto addVal = request.Pop<i32>();
|
auto addVal = request.Pop<i32>();
|
||||||
auto type = request.Pop<i32>();
|
auto type = request.Pop<i32>();
|
||||||
state.logger->Debug("Reference Change: {} {} reference", addVal, type ? "strong" : "weak");
|
state.logger->Debug("Reference Change: {} {} reference", addVal, type ? "strong" : "weak");
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHOSBinderDriver::GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHOSBinderDriver::GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
KHandle handle = state.process->InsertItem(state.gpu->bufferEvent);
|
KHandle handle = state.process->InsertItem(state.gpu->bufferEvent);
|
||||||
state.logger->Debug("Display Buffer Event Handle: 0x{:X}", handle);
|
state.logger->Debug("Display Buffer Event Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
response.Push<u32>(constant::status::Success);
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHOSBinderDriver::SetDisplay(const std::string &name) {
|
void IHOSBinderDriver::SetDisplay(const std::string &name) {
|
||||||
|
@ -48,6 +48,7 @@ namespace skyline::service::hosbinder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<u32, std::shared_ptr<Buffer>> queue; //!< A vector of shared pointers to all the queued buffers
|
std::unordered_map<u32, std::shared_ptr<Buffer>> queue; //!< A vector of shared pointers to all the queued buffers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This the GbpBuffer struct of the specified buffer
|
* @brief This the GbpBuffer struct of the specified buffer
|
||||||
*/
|
*/
|
||||||
@ -90,17 +91,17 @@ namespace skyline::service::hosbinder {
|
|||||||
/**
|
/**
|
||||||
* @brief This emulates the transaction of parcels between a IGraphicBufferProducer and the application (https://switchbrew.org/wiki/Nvnflinger_services#TransactParcel)
|
* @brief This emulates the transaction of parcels between a IGraphicBufferProducer and the application (https://switchbrew.org/wiki/Nvnflinger_services#TransactParcel)
|
||||||
*/
|
*/
|
||||||
void TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This adjusts the reference counts to the underlying binder, it is stubbed as we aren't using the real symbols (https://switchbrew.org/wiki/Nvnflinger_services#AdjustRefcount)
|
* @brief This adjusts the reference counts to the underlying binder, it is stubbed as we aren't using the real symbols (https://switchbrew.org/wiki/Nvnflinger_services#AdjustRefcount)
|
||||||
*/
|
*/
|
||||||
void AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This adjusts the reference counts to the underlying binder, it is stubbed as we aren't using the real symbols (https://switchbrew.org/wiki/Nvnflinger_services#GetNativeHandle)
|
* @brief This adjusts the reference counts to the underlying binder, it is stubbed as we aren't using the real symbols (https://switchbrew.org/wiki/Nvnflinger_services#GetNativeHandle)
|
||||||
*/
|
*/
|
||||||
void GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets displayId to a specific display type
|
* @brief This sets displayId to a specific display type
|
||||||
|
@ -9,7 +9,8 @@ namespace skyline::service::lm {
|
|||||||
{0x0, SFUNC(ILogService::OpenLogger)}
|
{0x0, SFUNC(ILogService::OpenLogger)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ILogService::OpenLogger(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ILogService::OpenLogger(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(ILogger), session, response);
|
manager.RegisterService(SRVREG(ILogger), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::lm {
|
|||||||
/**
|
/**
|
||||||
* @brief This opens an ILogger that can be used by applications to print log messages (https://switchbrew.org/wiki/Log_services#OpenLogger)
|
* @brief This opens an ILogger that can be used by applications to print log messages (https://switchbrew.org/wiki/Log_services#OpenLogger)
|
||||||
*/
|
*/
|
||||||
void OpenLogger(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result OpenLogger(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace skyline::service::lm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILogger::Log(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ILogger::Log(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u64 pid;
|
u64 pid;
|
||||||
u64 threadContext;
|
u64 threadContext;
|
||||||
@ -98,7 +98,10 @@ namespace skyline::service::lm {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILogger::SetDestination(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result ILogger::SetDestination(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,11 +53,11 @@ namespace skyline::service::lm {
|
|||||||
/**
|
/**
|
||||||
* @brief This prints a message to the log (https://switchbrew.org/wiki/Log_services#Log)
|
* @brief This prints a message to the log (https://switchbrew.org/wiki/Log_services#Log)
|
||||||
*/
|
*/
|
||||||
void Log(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Log(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the log destination (https://switchbrew.org/wiki/Log_services#SetDestination)
|
* @brief This sets the log destination (https://switchbrew.org/wiki/Log_services#SetDestination)
|
||||||
*/
|
*/
|
||||||
void SetDestination(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetDestination(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,7 @@ namespace skyline::service::nfp {
|
|||||||
{0x0, SFUNC(IUser::Initialize)}
|
{0x0, SFUNC(IUser::Initialize)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IUser::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IUser::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::nfp {
|
|||||||
/**
|
/**
|
||||||
* @brief This initializes an NFP session
|
* @brief This initializes an NFP session
|
||||||
*/
|
*/
|
||||||
void Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ namespace skyline::service::nfp {
|
|||||||
{0x0, SFUNC(IUserManager::CreateUserInterface)}
|
{0x0, SFUNC(IUserManager::CreateUserInterface)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IUserManager::CreateUserInterface(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IUserManager::CreateUserInterface(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IUser), session, response);
|
manager.RegisterService(SRVREG(IUser), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::nfp {
|
|||||||
/**
|
/**
|
||||||
* @brief This opens an IUser that can be used by applications to access NFC devices
|
* @brief This opens an IUser that can be used by applications to access NFC devices
|
||||||
*/
|
*/
|
||||||
void CreateUserInterface(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateUserInterface(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ namespace skyline::service::nifm {
|
|||||||
{0x4, SFUNC(IGeneralService::CreateRequest)}
|
{0x4, SFUNC(IGeneralService::CreateRequest)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IGeneralService::CreateRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IGeneralService::CreateRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IRequest), session, response);
|
manager.RegisterService(SRVREG(IRequest), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::nifm {
|
|||||||
/**
|
/**
|
||||||
* @brief This creates an IRequest instance that can be used to bring up the network (https://switchbrew.org/wiki/Network_Interface_services#CreateRequest)
|
* @brief This creates an IRequest instance that can be used to bring up the network (https://switchbrew.org/wiki/Network_Interface_services#CreateRequest)
|
||||||
*/
|
*/
|
||||||
void CreateRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,17 @@ namespace skyline::service::nifm {
|
|||||||
{0x4, SFUNC(IRequest::Submit)},
|
{0x4, SFUNC(IRequest::Submit)},
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IRequest::GetRequestState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IRequest::GetRequestState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
constexpr u32 Unsubmitted = 1; //!< The request has not been submitted
|
constexpr u32 Unsubmitted = 1; //!< The request has not been submitted
|
||||||
response.Push<u32>(Unsubmitted);
|
response.Push<u32>(Unsubmitted);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRequest::GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IRequest::GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void IRequest::GetSystemEventReadableHandles(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IRequest::GetSystemEventReadableHandles(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle = state.process->InsertItem(event0);
|
auto handle = state.process->InsertItem(event0);
|
||||||
state.logger->Debug("Request Event 0 Handle: 0x{:X}", handle);
|
state.logger->Debug("Request Event 0 Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
@ -27,7 +30,11 @@ namespace skyline::service::nifm {
|
|||||||
handle = state.process->InsertItem(event1);
|
handle = state.process->InsertItem(event1);
|
||||||
state.logger->Debug("Request Event 1 Handle: 0x{:X}", handle);
|
state.logger->Debug("Request Event 1 Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRequest::Submit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IRequest::Submit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,21 @@ namespace skyline::service::nifm {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns the current state of the request (https://switchbrew.org/wiki/Network_Interface_services#GetRequestState)
|
* @brief This returns the current state of the request (https://switchbrew.org/wiki/Network_Interface_services#GetRequestState)
|
||||||
*/
|
*/
|
||||||
void GetRequestState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetRequestState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the error code if a network bring up request fails (https://switchbrew.org/wiki/Network_Interface_services#GetResult)
|
* @brief This returns the error code if a network bring up request fails (https://switchbrew.org/wiki/Network_Interface_services#GetResult)
|
||||||
*/
|
*/
|
||||||
void GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns two KEvent handles that signal request on request updates (https://switchbrew.org/wiki/Network_Interface_services#GetSystemEventReadableHandles)
|
* @brief This returns two KEvent handles that signal request on request updates (https://switchbrew.org/wiki/Network_Interface_services#GetSystemEventReadableHandles)
|
||||||
*/
|
*/
|
||||||
void GetSystemEventReadableHandles(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSystemEventReadableHandles(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This submits a request to bring up a network (https://switchbrew.org/wiki/Network_Interface_services#Submit)
|
* @brief This submits a request to bring up a network (https://switchbrew.org/wiki/Network_Interface_services#Submit)
|
||||||
*/
|
*/
|
||||||
void Submit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Submit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,8 @@ namespace skyline::service::nifm {
|
|||||||
{0x5, SFUNC(IStaticService::CreateGeneralService)}
|
{0x5, SFUNC(IStaticService::CreateGeneralService)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IStaticService::CreateGeneralService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IStaticService::CreateGeneralService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IGeneralService), session, response);
|
manager.RegisterService(SRVREG(IGeneralService), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::nifm {
|
|||||||
/**
|
/**
|
||||||
* @brief This opens an IGeneralService that can be used by applications to control the network connection (https://switchbrew.org/wiki/Network_Interface_services#CreateGeneralServiceOld)
|
* @brief This opens an IGeneralService that can be used by applications to control the network connection (https://switchbrew.org/wiki/Network_Interface_services#CreateGeneralServiceOld)
|
||||||
*/
|
*/
|
||||||
void CreateGeneralService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateGeneralService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -64,15 +64,17 @@ namespace skyline::service::nvdrv {
|
|||||||
{0xD, SFUNC(INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled)}
|
{0xD, SFUNC(INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void INvDrvServices::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto buffer = request.inputBuf.at(0);
|
auto buffer = request.inputBuf.at(0);
|
||||||
auto path = state.process->GetString(buffer.address, buffer.size);
|
auto path = state.process->GetString(buffer.address, buffer.size);
|
||||||
|
|
||||||
response.Push<u32>(OpenDevice(path));
|
response.Push<u32>(OpenDevice(path));
|
||||||
response.Push<u32>(constant::status::Success);
|
response.Push(device::NvStatus::Success);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void INvDrvServices::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto fd = request.Pop<u32>();
|
auto fd = request.Pop<u32>();
|
||||||
auto cmd = request.Pop<u32>();
|
auto cmd = request.Pop<u32>();
|
||||||
|
|
||||||
@ -87,25 +89,27 @@ namespace skyline::service::nvdrv {
|
|||||||
device::IoctlData data(request.outputBuf.at(0));
|
device::IoctlData data(request.outputBuf.at(0));
|
||||||
|
|
||||||
fdMap.at(fd)->HandleIoctl(cmd, data);
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
||||||
response.Push<u32>(data.status);
|
response.Push(data.status);
|
||||||
} else {
|
} else {
|
||||||
device::IoctlData data(request.inputBuf.at(0));
|
device::IoctlData data(request.inputBuf.at(0));
|
||||||
|
|
||||||
fdMap.at(fd)->HandleIoctl(cmd, data);
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
||||||
response.Push<u32>(data.status);
|
response.Push(data.status);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
device::IoctlData data(request.inputBuf.at(0), request.outputBuf.at(0));
|
device::IoctlData data(request.inputBuf.at(0), request.outputBuf.at(0));
|
||||||
|
|
||||||
fdMap.at(fd)->HandleIoctl(cmd, data);
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
||||||
response.Push<u32>(data.status);
|
response.Push(data.status);
|
||||||
}
|
}
|
||||||
} catch (const std::out_of_range &) {
|
} catch (const std::out_of_range &) {
|
||||||
throw exception("IOCTL was requested on an invalid file descriptor");
|
throw exception("IOCTL was requested on an invalid file descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto fd = request.Pop<u32>();
|
auto fd = request.Pop<u32>();
|
||||||
state.logger->Debug("Closing NVDRV device ({})", fd);
|
state.logger->Debug("Closing NVDRV device ({})", fd);
|
||||||
|
|
||||||
@ -119,14 +123,16 @@ namespace skyline::service::nvdrv {
|
|||||||
state.logger->Warn("Trying to close non-existent FD");
|
state.logger->Warn("Trying to close non-existent FD");
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Push<u32>(constant::status::Success);
|
response.Push(device::NvStatus::Success);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void INvDrvServices::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u32>(constant::status::Success);
|
response.Push(device::NvStatus::Success);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void INvDrvServices::QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto fd = request.Pop<u32>();
|
auto fd = request.Pop<u32>();
|
||||||
auto eventId = request.Pop<u32>();
|
auto eventId = request.Pop<u32>();
|
||||||
auto device = fdMap.at(fd);
|
auto device = fdMap.at(fd);
|
||||||
@ -138,15 +144,20 @@ namespace skyline::service::nvdrv {
|
|||||||
state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", fd, eventId, handle);
|
state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", fd, eventId, handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
|
||||||
response.Push<u32>(device::NvStatus::Success);
|
response.Push(device::NvStatus::Success);
|
||||||
} else {
|
} else {
|
||||||
response.Push<u32>(device::NvStatus::BadValue);
|
response.Push(device::NvStatus::BadValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void INvDrvServices::SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u32>(constant::status::Success);
|
response.Push(device::NvStatus::Success);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,36 +67,36 @@ namespace skyline::service::nvdrv {
|
|||||||
/**
|
/**
|
||||||
* @brief Open a specific device and return a FD (https://switchbrew.org/wiki/NV_services#Open)
|
* @brief Open a specific device and return a FD (https://switchbrew.org/wiki/NV_services#Open)
|
||||||
*/
|
*/
|
||||||
void Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close the specified FD (https://switchbrew.org/wiki/NV_services#Close)
|
* @brief Close the specified FD (https://switchbrew.org/wiki/NV_services#Close)
|
||||||
*/
|
*/
|
||||||
void Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close the specified FD (https://switchbrew.org/wiki/NV_services#Close)
|
* @brief Close the specified FD (https://switchbrew.org/wiki/NV_services#Close)
|
||||||
*/
|
*/
|
||||||
void Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This initializes the driver (https://switchbrew.org/wiki/NV_services#Initialize)
|
* @brief This initializes the driver (https://switchbrew.org/wiki/NV_services#Initialize)
|
||||||
*/
|
*/
|
||||||
void Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a specific event from a device (https://switchbrew.org/wiki/NV_services#QueryEvent)
|
* @brief This returns a specific event from a device (https://switchbrew.org/wiki/NV_services#QueryEvent)
|
||||||
*/
|
*/
|
||||||
void QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the AppletResourceUserId which matches the PID (https://switchbrew.org/wiki/NV_services#SetAruidByPID)
|
* @brief This sets the AppletResourceUserId which matches the PID (https://switchbrew.org/wiki/NV_services#SetAruidByPID)
|
||||||
*/
|
*/
|
||||||
void SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This enables the graphics firmware memory margin (https://switchbrew.org/wiki/NV_services#SetGraphicsFirmwareMemoryMarginEnabled)
|
* @brief This enables the graphics firmware memory margin (https://switchbrew.org/wiki/NV_services#SetGraphicsFirmwareMemoryMarginEnabled)
|
||||||
*/
|
*/
|
||||||
void SetGraphicsFirmwareMemoryMarginEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetGraphicsFirmwareMemoryMarginEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace skyline::service::nvdrv::device {
|
|||||||
/**
|
/**
|
||||||
* @brief This enumerates all the possible error codes returned by the Nvidia driver (https://switchbrew.org/wiki/NV_services#Errors)
|
* @brief This enumerates all the possible error codes returned by the Nvidia driver (https://switchbrew.org/wiki/NV_services#Errors)
|
||||||
*/
|
*/
|
||||||
enum NvStatus : u32 {
|
enum class NvStatus : u32 {
|
||||||
Success = 0x0, //!< The operation has succeeded
|
Success = 0x0, //!< The operation has succeeded
|
||||||
NotImplemented = 0x1, //!< The operation is not implemented
|
NotImplemented = 0x1, //!< The operation is not implemented
|
||||||
NotSupported = 0x2, //!< The operation is not supported
|
NotSupported = 0x2, //!< The operation is not supported
|
||||||
|
@ -106,44 +106,37 @@ namespace skyline::service::nvdrv::device {
|
|||||||
u32 result; // Out
|
u32 result; // Out
|
||||||
} data = state.process->GetObject<Data>(buffer.input[0].address);
|
} data = state.process->GetObject<Data>(buffer.input[0].address);
|
||||||
|
|
||||||
auto &object = handleTable.at(data.handle);
|
try {
|
||||||
switch (data.parameter) {
|
auto &object = handleTable.at(data.handle);
|
||||||
case Parameter::Size:
|
|
||||||
data.result = object->size;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Parameter::Alignment:
|
|
||||||
case Parameter::HeapMask:
|
switch (data.parameter) {
|
||||||
case Parameter::Kind: {
|
case Parameter::Size:
|
||||||
if (object->status != NvMapObject::Status::Allocated)
|
data.result = object->size;
|
||||||
data.result = NvStatus::BadParameter;
|
break;
|
||||||
switch (data.parameter) {
|
case Parameter::Alignment:
|
||||||
case Parameter::Alignment:
|
data.result = object->align;
|
||||||
data.result = object->align;
|
break;
|
||||||
break;
|
case Parameter::HeapMask:
|
||||||
case Parameter::HeapMask:
|
data.result = object->heapMask;
|
||||||
data.result = object->heapMask;
|
break;
|
||||||
break;
|
case Parameter::Kind:
|
||||||
case Parameter::Kind:
|
data.result = object->kind;
|
||||||
data.result = object->kind;
|
break;
|
||||||
break;
|
case Parameter::Compr:
|
||||||
default:
|
data.result = 0;
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
break;
|
buffer.status = NvStatus::NotImplemented;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Parameter::Base:
|
state.process->WriteMemory(data, buffer.output[0].address);
|
||||||
buffer.status = NvStatus::NotImplemented;
|
state.logger->Debug("Param: Input: Handle: 0x{:X}, Parameter: {}, Output: Result: 0x{:X}, Status: {}", data.handle, data.parameter, data.result, buffer.status);
|
||||||
break;
|
} catch (std::exception &e) {
|
||||||
|
buffer.status = NvStatus::BadParameter;
|
||||||
case Parameter::Compr:
|
return;
|
||||||
buffer.status = NvStatus::NotImplemented;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.process->WriteMemory(data, buffer.output[0].address);
|
|
||||||
state.logger->Debug("Param: Input: Handle: 0x{:X}, Parameter: {}, Output: Result: 0x{:X}, Status: {}", data.handle, data.parameter, data.result, buffer.status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvMap::GetId(IoctlData &buffer) {
|
void NvMap::GetId(IoctlData &buffer) {
|
||||||
|
@ -10,7 +10,8 @@ namespace skyline::service::pctl {
|
|||||||
{0x1, SFUNC(IParentalControlServiceFactory::CreateService)}
|
{0x1, SFUNC(IParentalControlServiceFactory::CreateService)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IParentalControlServiceFactory::CreateService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IParentalControlServiceFactory::CreateService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
manager.RegisterService(SRVREG(IParentalControlService), session, response);
|
manager.RegisterService(SRVREG(IParentalControlService), session, response);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::pctl {
|
|||||||
/**
|
/**
|
||||||
* @brief This creates and initializes an IParentalControlService instance that can be used to read parental control configuration
|
* @brief This creates and initializes an IParentalControlService instance that can be used to read parental control configuration
|
||||||
*/
|
*/
|
||||||
void CreateService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result CreateService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -50,26 +50,30 @@ namespace skyline::service::pl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPlatformServiceManager::GetLoadState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IPlatformServiceManager::GetLoadState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
constexpr u32 FontLoaded = 1; //!< This is returned to show that all fonts have been loaded into memory
|
constexpr u32 FontLoaded = 1; //!< This is returned to show that all fonts have been loaded into memory
|
||||||
|
|
||||||
response.Push(FontLoaded);
|
response.Push(FontLoaded);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPlatformServiceManager::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IPlatformServiceManager::GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto fontId = request.Pop<u32>();
|
auto fontId = request.Pop<u32>();
|
||||||
|
|
||||||
response.Push<u32>(fontTable.at(fontId).length);
|
response.Push<u32>(fontTable.at(fontId).length);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPlatformServiceManager::GetSharedMemoryAddressOffset(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IPlatformServiceManager::GetSharedMemoryAddressOffset(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto fontId = request.Pop<u32>();
|
auto fontId = request.Pop<u32>();
|
||||||
|
|
||||||
response.Push<u32>(fontTable.at(fontId).offset);
|
response.Push<u32>(fontTable.at(fontId).offset);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPlatformServiceManager::GetSharedMemoryNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IPlatformServiceManager::GetSharedMemoryNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto handle = state.process->InsertItem<type::KSharedMemory>(fontSharedMem);
|
auto handle = state.process->InsertItem<type::KSharedMemory>(fontSharedMem);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,22 +25,22 @@ namespace skyline {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns the loading state of the requested font (https://switchbrew.org/wiki/Shared_Database_services#GetLoadState)
|
* @brief This returns the loading state of the requested font (https://switchbrew.org/wiki/Shared_Database_services#GetLoadState)
|
||||||
*/
|
*/
|
||||||
void GetLoadState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetLoadState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the size of the requested font (https://switchbrew.org/wiki/Shared_Database_services#GetSize)
|
* @brief This returns the size of the requested font (https://switchbrew.org/wiki/Shared_Database_services#GetSize)
|
||||||
*/
|
*/
|
||||||
void GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the offset in shared memory of the requested font (https://switchbrew.org/wiki/Shared_Database_services#GetSharedMemoryAddressOffset)
|
* @brief This returns the offset in shared memory of the requested font (https://switchbrew.org/wiki/Shared_Database_services#GetSharedMemoryAddressOffset)
|
||||||
*/
|
*/
|
||||||
void GetSharedMemoryAddressOffset(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSharedMemoryAddressOffset(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a handle to the whole font shared memory (https://switchbrew.org/wiki/Shared_Database_services#GetSharedMemoryNativeHandle)
|
* @brief This returns a handle to the whole font shared memory (https://switchbrew.org/wiki/Shared_Database_services#GetSharedMemoryNativeHandle)
|
||||||
*/
|
*/
|
||||||
void GetSharedMemoryNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetSharedMemoryNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,7 @@ namespace skyline::service::prepo {
|
|||||||
{0x2775, SFUNC(IPrepoService::SaveReportWithUser)},
|
{0x2775, SFUNC(IPrepoService::SaveReportWithUser)},
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IPrepoService::SaveReportWithUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
Result IPrepoService::SaveReportWithUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ namespace skyline::service::prepo {
|
|||||||
/**
|
/**
|
||||||
* @brief This saves a play report for the given user
|
* @brief This saves a play report for the given user
|
||||||
*/
|
*/
|
||||||
void SaveReportWithUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SaveReportWithUser(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ namespace skyline::service {
|
|||||||
auto service = session->domainTable.at(request.domain->objectId);
|
auto service = session->domainTable.at(request.domain->objectId);
|
||||||
switch (static_cast<ipc::DomainCommand>(request.domain->command)) {
|
switch (static_cast<ipc::DomainCommand>(request.domain->command)) {
|
||||||
case ipc::DomainCommand::SendMessage:
|
case ipc::DomainCommand::SendMessage:
|
||||||
service->HandleRequest(*session, request, response);
|
response.errorCode = service->HandleRequest(*session, request, response);
|
||||||
break;
|
break;
|
||||||
case ipc::DomainCommand::CloseVHandle:
|
case ipc::DomainCommand::CloseVHandle:
|
||||||
std::erase_if(serviceMap, [service](const auto &entry) {
|
std::erase_if(serviceMap, [service](const auto &entry) {
|
||||||
@ -167,7 +167,7 @@ namespace skyline::service {
|
|||||||
throw exception("Invalid object ID was used with domain request");
|
throw exception("Invalid object ID was used with domain request");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
session->serviceObject->HandleRequest(*session, request, response);
|
response.errorCode = session->serviceObject->HandleRequest(*session, request, response);
|
||||||
}
|
}
|
||||||
response.WriteResponse(session->isDomain);
|
response.WriteResponse(session->isDomain);
|
||||||
break;
|
break;
|
||||||
|
@ -31,19 +31,22 @@ namespace skyline::service::settings {
|
|||||||
util::MakeMagic<u64>("zh-Hant"),
|
util::MakeMagic<u64>("zh-Hant"),
|
||||||
};
|
};
|
||||||
|
|
||||||
void ISettingsServer::GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISettingsServer::GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.process->WriteMemory(LanguageCodeList.data(), request.outputBuf.at(0).address, constant::OldLanguageCodeListSize * sizeof(u64));
|
state.process->WriteMemory(LanguageCodeList.data(), request.outputBuf.at(0).address, constant::OldLanguageCodeListSize * sizeof(u64));
|
||||||
|
|
||||||
response.Push<i32>(constant::OldLanguageCodeListSize);
|
response.Push<i32>(constant::OldLanguageCodeListSize);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISettingsServer::MakeLanguageCode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISettingsServer::MakeLanguageCode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push<u64>(LanguageCodeList.at(request.Pop<i32>()));
|
response.Push<u64>(LanguageCodeList.at(request.Pop<i32>()));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISettingsServer::GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISettingsServer::GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.process->WriteMemory(LanguageCodeList.data(), request.outputBuf.at(0).address, constant::NewLanguageCodeListSize * sizeof(u64));
|
state.process->WriteMemory(LanguageCodeList.data(), request.outputBuf.at(0).address, constant::NewLanguageCodeListSize * sizeof(u64));
|
||||||
|
|
||||||
response.Push<i32>(constant::NewLanguageCodeListSize);
|
response.Push<i32>(constant::NewLanguageCodeListSize);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,17 @@ namespace skyline::service {
|
|||||||
/**
|
/**
|
||||||
* @brief This reads the available language codes that an application can use (pre 4.0.0)
|
* @brief This reads the available language codes that an application can use (pre 4.0.0)
|
||||||
*/
|
*/
|
||||||
void GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This converts a language code list index to it's corresponding language code
|
* @brief This converts a language code list index to it's corresponding language code
|
||||||
*/
|
*/
|
||||||
void MakeLanguageCode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result MakeLanguageCode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This reads the available language codes that an application can use (post 4.0.0)
|
* @brief This reads the available language codes that an application can use (post 4.0.0)
|
||||||
*/
|
*/
|
||||||
void GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,9 @@ namespace skyline::service::settings {
|
|||||||
ISystemSettingsServer::ISystemSettingsServer(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, {
|
ISystemSettingsServer::ISystemSettingsServer(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, {
|
||||||
{0x3, SFUNC(ISystemSettingsServer::GetFirmwareVersion)}}) {}
|
{0x3, SFUNC(ISystemSettingsServer::GetFirmwareVersion)}}) {}
|
||||||
|
|
||||||
void ISystemSettingsServer::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result ISystemSettingsServer::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
SysVerTitle title{.major=9, .minor=0, .micro=0, .revMajor=4, .revMinor=0, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
SysVerTitle title{.major=9, .minor=0, .micro=0, .revMajor=4, .revMinor=0, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
||||||
state.process->WriteMemory(title, request.outputBuf.at(0).address);
|
state.process->WriteMemory(title, request.outputBuf.at(0).address);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user