mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 15:35:29 +03:00
Improve IPC interface
This commit changes how IPC is interacted with in two ways: * Simplify all buffers into just InputBuffer and OutputBuffer * Use pushing/popping for data payload
This commit is contained in:
parent
745cb208a6
commit
38716989ae
@ -122,24 +122,21 @@ namespace skyline::gpu {
|
|||||||
void GPU::Ioctl(u32 fd, u32 cmd, kernel::ipc::IpcRequest &request, kernel::ipc::IpcResponse &response) {
|
void GPU::Ioctl(u32 fd, u32 cmd, kernel::ipc::IpcRequest &request, kernel::ipc::IpcResponse &response) {
|
||||||
state.logger->Debug("IOCTL on device: 0x{:X}, cmd: 0x{:X}", fd, cmd);
|
state.logger->Debug("IOCTL on device: 0x{:X}, cmd: 0x{:X}", fd, cmd);
|
||||||
try {
|
try {
|
||||||
if (!request.vecBufA.empty() && !request.vecBufB.empty()) {
|
if(request.inputBuf.empty() || request.outputBuf.empty()) {
|
||||||
device::IoctlBuffers input(device::InputBuffer(request.vecBufA[0]), device::OutputBuffer(request.vecBufB[0]));
|
if(request.inputBuf.empty()) {
|
||||||
fdMap.at(fd)->HandleIoctl(cmd, input);
|
device::IoctlData data(request.outputBuf.at(0));
|
||||||
response.WriteValue<u32>(input.status);
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
||||||
} else if (!request.vecBufX.empty() && !request.vecBufC.empty()) {
|
response.Push<u32>(data.status);
|
||||||
device::IoctlBuffers input(device::InputBuffer(request.vecBufX[0]), device::OutputBuffer(request.vecBufC[0]));
|
} else {
|
||||||
fdMap.at(fd)->HandleIoctl(cmd, input);
|
device::IoctlData data(request.inputBuf.at(0));
|
||||||
response.WriteValue<u32>(input.status);
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
||||||
} else if (!request.vecBufX.empty()) {
|
response.Push<u32>(data.status);
|
||||||
device::IoctlBuffers input(device::InputBuffer(request.vecBufX[0]));
|
}
|
||||||
fdMap.at(fd)->HandleIoctl(cmd, input);
|
} else {
|
||||||
response.WriteValue<u32>(input.status);
|
device::IoctlData data(request.inputBuf.at(0), request.outputBuf.at(0));
|
||||||
} else if (!request.vecBufC.empty()) {
|
fdMap.at(fd)->HandleIoctl(cmd, data);
|
||||||
device::IoctlBuffers input(device::OutputBuffer(request.vecBufC[0]));
|
response.Push<u32>(data.status);
|
||||||
fdMap.at(fd)->HandleIoctl(cmd, input);
|
}
|
||||||
response.WriteValue<u32>(input.status);
|
|
||||||
} else
|
|
||||||
throw exception("Unknown IOCTL buffer configuration");
|
|
||||||
} 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");
|
||||||
}
|
}
|
||||||
|
@ -54,50 +54,6 @@ namespace skyline::gpu::device {
|
|||||||
{"/dev/nvhost-ctrl-gpu", NvDeviceType::nvhost_ctrl_gpu}
|
{"/dev/nvhost-ctrl-gpu", NvDeviceType::nvhost_ctrl_gpu}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Describes a buffer by holding the address and size
|
|
||||||
*/
|
|
||||||
struct IoctlBuffer {
|
|
||||||
u64 address; //!< The address of the buffer
|
|
||||||
size_t size; //!< The size of the buffer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param address The address of the buffer
|
|
||||||
* @param size The size of the buffer
|
|
||||||
*/
|
|
||||||
IoctlBuffer(u64 address, size_t size) : address(address), size(size) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Wrapper around IoctlBuffer that loads in the address from a A Buffer Descriptor
|
|
||||||
*/
|
|
||||||
struct InputBuffer : public IoctlBuffer {
|
|
||||||
/**
|
|
||||||
* @param aBuf The A Buffer Descriptor that has contains the input data
|
|
||||||
*/
|
|
||||||
InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf) : IoctlBuffer(aBuf->Address(), aBuf->Size()) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param aBuf The X Buffer Descriptor that has contains the input data
|
|
||||||
*/
|
|
||||||
InputBuffer(kernel::ipc::BufferDescriptorX *xBuf) : IoctlBuffer(xBuf->Address(), xBuf->size) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Wrapper around IoctlBuffer that loads in the address from a B Buffer Descriptor
|
|
||||||
*/
|
|
||||||
struct OutputBuffer : public IoctlBuffer {
|
|
||||||
/**
|
|
||||||
* @param aBuf The B Buffer Descriptor that has to be outputted to
|
|
||||||
*/
|
|
||||||
OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf) : IoctlBuffer(bBuf->Address(), bBuf->Size()) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param xBuf The C Buffer Descriptor that has to be outputted to
|
|
||||||
*/
|
|
||||||
OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf) : IoctlBuffer(cBuf->address, cBuf->size) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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)
|
||||||
*/
|
*/
|
||||||
@ -128,11 +84,11 @@ namespace skyline::gpu::device {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This holds all the IoctlBuffer objects in a coherent container
|
* @brief This holds all the input and output data for an IOCTL function
|
||||||
*/
|
*/
|
||||||
struct IoctlBuffers {
|
struct IoctlData {
|
||||||
std::vector<InputBuffer> input; //!< A vector of all input IOCTL buffers
|
std::vector<kernel::ipc::InputBuffer> input; //!< A vector of all input IOCTL buffers
|
||||||
std::vector<OutputBuffer> output; //!< A vector of all output IOCTL buffers
|
std::vector<kernel::ipc::OutputBuffer> output; //!< A vector of all output IOCTL buffers
|
||||||
NvStatus status{NvStatus::Success}; //!< The error code that is returned to the application
|
NvStatus status{NvStatus::Success}; //!< The error code that is returned to the application
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,19 +96,19 @@ namespace skyline::gpu::device {
|
|||||||
* @param input An input buffer
|
* @param input An input buffer
|
||||||
* @param output An output buffer
|
* @param output An output buffer
|
||||||
*/
|
*/
|
||||||
IoctlBuffers(InputBuffer input, OutputBuffer output) : input({input}), output({output}) {}
|
IoctlData(kernel::ipc::InputBuffer input, kernel::ipc::OutputBuffer output) : input({input}), output({output}) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This constructor takes 1 input buffer, it's used for Ioctl sometimes
|
* @brief This constructor takes 1 input buffer, it's used for Ioctl sometimes
|
||||||
* @param output An output buffer
|
* @param output An output buffer
|
||||||
*/
|
*/
|
||||||
IoctlBuffers(InputBuffer input) : input({input}) {}
|
IoctlData(kernel::ipc::InputBuffer input) : input({input}) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This constructor takes 1 output buffer, it's used for Ioctl sometimes
|
* @brief This constructor takes 1 output buffer, it's used for Ioctl sometimes
|
||||||
* @param output An output buffer
|
* @param output An output buffer
|
||||||
*/
|
*/
|
||||||
IoctlBuffers(OutputBuffer output) : output({output}) {}
|
IoctlData(kernel::ipc::OutputBuffer output) : output({output}) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This constructor takes 2 input buffers and 1 output buffer, it's used for Ioctl1
|
* @brief This constructor takes 2 input buffers and 1 output buffer, it's used for Ioctl1
|
||||||
@ -160,7 +116,7 @@ namespace skyline::gpu::device {
|
|||||||
* @param input2 The second input buffer
|
* @param input2 The second input buffer
|
||||||
* @param output An output buffer
|
* @param output An output buffer
|
||||||
*/
|
*/
|
||||||
IoctlBuffers(InputBuffer input1, InputBuffer input2, OutputBuffer output) : input({input1, input2}), output({output}) {}
|
IoctlData(kernel::ipc::InputBuffer input1, kernel::ipc::InputBuffer input2, kernel::ipc::OutputBuffer output) : input({input1, input2}), output({output}) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This constructor takes 1 input buffer and 2 output buffers, it's used for Ioctl2
|
* @brief This constructor takes 1 input buffer and 2 output buffers, it's used for Ioctl2
|
||||||
@ -168,7 +124,7 @@ namespace skyline::gpu::device {
|
|||||||
* @param output1 The first output buffer
|
* @param output1 The first output buffer
|
||||||
* @param output2 The second output buffer
|
* @param output2 The second output buffer
|
||||||
*/
|
*/
|
||||||
IoctlBuffers(InputBuffer input, OutputBuffer output1, OutputBuffer output2) : input({input}), output({output1, output2}) {}
|
IoctlData(kernel::ipc::InputBuffer input, kernel::ipc::OutputBuffer output1, kernel::ipc::OutputBuffer output2) : input({input}), output({output1, output2}) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,7 +133,7 @@ namespace skyline::gpu::device {
|
|||||||
class NvDevice {
|
class NvDevice {
|
||||||
protected:
|
protected:
|
||||||
const DeviceState &state; //!< The state of the device
|
const DeviceState &state; //!< The state of the device
|
||||||
std::unordered_map<u32, std::function<void(IoctlBuffers &)>> vTable; //!< This holds the mapping from an Ioctl to the actual function
|
std::unordered_map<u32, std::function<void(IoctlData &)>> vTable; //!< This holds the mapping from an Ioctl to the actual function
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u16 refCount{1}; //!< The amount of handles to the device
|
u16 refCount{1}; //!< The amount of handles to the device
|
||||||
@ -188,7 +144,7 @@ namespace skyline::gpu::device {
|
|||||||
* @param deviceType The type of the device
|
* @param deviceType The type of the device
|
||||||
* @param vTable The functions in this device
|
* @param vTable The functions in this device
|
||||||
*/
|
*/
|
||||||
NvDevice(const DeviceState &state, NvDeviceType deviceType, std::unordered_map<u32, std::function<void(IoctlBuffers &)>> vTable) : state(state), deviceType(deviceType), vTable(vTable) {}
|
NvDevice(const DeviceState &state, NvDeviceType deviceType, std::unordered_map<u32, std::function<void(IoctlData &)>> vTable) : state(state), deviceType(deviceType), vTable(vTable) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the name of the current service
|
* @brief This returns the name of the current service
|
||||||
@ -208,8 +164,8 @@ namespace skyline::gpu::device {
|
|||||||
* @param cmd The IOCTL command that was called
|
* @param cmd The IOCTL command that was called
|
||||||
* @param input The input to the IOCTL call
|
* @param input The input to the IOCTL call
|
||||||
*/
|
*/
|
||||||
void HandleIoctl(u32 cmd, IoctlBuffers &input) {
|
void HandleIoctl(u32 cmd, IoctlData &input) {
|
||||||
std::function<void(IoctlBuffers &)> function;
|
std::function<void(IoctlData &)> function;
|
||||||
try {
|
try {
|
||||||
function = vTable.at(cmd);
|
function = vTable.at(cmd);
|
||||||
} catch (std::out_of_range &) {
|
} catch (std::out_of_range &) {
|
||||||
|
@ -12,15 +12,15 @@ namespace skyline::gpu::device {
|
|||||||
{0x40084714, NFUNC(NvHostChannel::SetUserData)}
|
{0x40084714, NFUNC(NvHostChannel::SetUserData)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void NvHostChannel::SetNvmapFd(skyline::gpu::device::IoctlBuffers &buffer) {}
|
void NvHostChannel::SetNvmapFd(skyline::gpu::device::IoctlData &buffer) {}
|
||||||
|
|
||||||
void NvHostChannel::AllocObjCtx(skyline::gpu::device::IoctlBuffers &buffer) {}
|
void NvHostChannel::AllocObjCtx(skyline::gpu::device::IoctlData &buffer) {}
|
||||||
|
|
||||||
void NvHostChannel::ZcullBind(IoctlBuffers &buffer) {}
|
void NvHostChannel::ZcullBind(IoctlData &buffer) {}
|
||||||
|
|
||||||
void NvHostChannel::SetErrorNotifier(skyline::gpu::device::IoctlBuffers &buffer) {}
|
void NvHostChannel::SetErrorNotifier(skyline::gpu::device::IoctlData &buffer) {}
|
||||||
|
|
||||||
void NvHostChannel::SetPriority(skyline::gpu::device::IoctlBuffers &buffer) {
|
void NvHostChannel::SetPriority(skyline::gpu::device::IoctlData &buffer) {
|
||||||
auto priority = state.thisProcess->ReadMemory<NvChannelPriority>(buffer.input[0].address);
|
auto priority = state.thisProcess->ReadMemory<NvChannelPriority>(buffer.input[0].address);
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
case NvChannelPriority::Low:
|
case NvChannelPriority::Low:
|
||||||
@ -35,8 +35,8 @@ namespace skyline::gpu::device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvHostChannel::AllocGpfifoEx2(skyline::gpu::device::IoctlBuffers &buffer) {}
|
void NvHostChannel::AllocGpfifoEx2(skyline::gpu::device::IoctlData &buffer) {}
|
||||||
|
|
||||||
void NvHostChannel::SetUserData(skyline::gpu::device::IoctlBuffers &buffer) {}
|
void NvHostChannel::SetUserData(skyline::gpu::device::IoctlData &buffer) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,36 +22,36 @@ namespace skyline::gpu::device {
|
|||||||
/**
|
/**
|
||||||
* @brief This sets the nvmap file descriptor (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD)
|
* @brief This sets the nvmap file descriptor (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD)
|
||||||
*/
|
*/
|
||||||
void SetNvmapFd(IoctlBuffers &buffer);
|
void SetNvmapFd(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This allocates a graphic context object (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX)
|
* @brief This allocates a graphic context object (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX)
|
||||||
*/
|
*/
|
||||||
void AllocObjCtx(IoctlBuffers &buffer);
|
void AllocObjCtx(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ZCULL_BIND)
|
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ZCULL_BIND)
|
||||||
*/
|
*/
|
||||||
void ZcullBind(IoctlBuffers &buffer);
|
void ZcullBind(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER)
|
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER)
|
||||||
*/
|
*/
|
||||||
void SetErrorNotifier(IoctlBuffers &buffer);
|
void SetErrorNotifier(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the priority of the channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_PRIORITY)
|
* @brief This sets the priority of the channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_PRIORITY)
|
||||||
*/
|
*/
|
||||||
void SetPriority(IoctlBuffers &buffer);
|
void SetPriority(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This allocates a GPFIFO entry (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2)
|
* @brief This allocates a GPFIFO entry (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2)
|
||||||
*/
|
*/
|
||||||
void AllocGpfifoEx2(IoctlBuffers &buffer);
|
void AllocGpfifoEx2(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the user specific data (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_USER_DATA)
|
* @brief This sets the user specific data (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_USER_DATA)
|
||||||
*/
|
*/
|
||||||
void SetUserData(IoctlBuffers &buffer);
|
void SetUserData(IoctlData &buffer);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,12 @@ namespace skyline::gpu::device {
|
|||||||
{0x80084714, NFUNC(NvHostCtrlGpu::GetActiveSlotMask)}
|
{0x80084714, NFUNC(NvHostCtrlGpu::GetActiveSlotMask)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void NvHostCtrlGpu::ZCullGetCtxSize(IoctlBuffers &buffer) {
|
void NvHostCtrlGpu::ZCullGetCtxSize(IoctlData &buffer) {
|
||||||
u32 size = 0x1;
|
u32 size = 0x1;
|
||||||
state.thisProcess->WriteMemory(size, buffer.output[0].address);
|
state.thisProcess->WriteMemory(size, buffer.output[0].address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvHostCtrlGpu::ZCullGetInfo(skyline::gpu::device::IoctlBuffers &buffer) {
|
void NvHostCtrlGpu::ZCullGetInfo(skyline::gpu::device::IoctlData &buffer) {
|
||||||
struct {
|
struct {
|
||||||
u32 widthAlignPixels{0x20};
|
u32 widthAlignPixels{0x20};
|
||||||
u32 heightAlignPixels{0x20};
|
u32 heightAlignPixels{0x20};
|
||||||
@ -31,7 +31,7 @@ namespace skyline::gpu::device {
|
|||||||
state.thisProcess->WriteMemory(zCullInfo, buffer.output[0].address);
|
state.thisProcess->WriteMemory(zCullInfo, buffer.output[0].address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvHostCtrlGpu::GetCharacteristics(IoctlBuffers &buffer) {
|
void NvHostCtrlGpu::GetCharacteristics(IoctlData &buffer) {
|
||||||
struct GpuCharacteristics {
|
struct GpuCharacteristics {
|
||||||
u32 arch; // 0x120 (NVGPU_GPU_ARCH_GM200)
|
u32 arch; // 0x120 (NVGPU_GPU_ARCH_GM200)
|
||||||
u32 impl; // 0xB (NVGPU_GPU_IMPL_GM20B) or 0xE (NVGPU_GPU_IMPL_GM20B_B)
|
u32 impl; // 0xB (NVGPU_GPU_IMPL_GM20B) or 0xE (NVGPU_GPU_IMPL_GM20B_B)
|
||||||
@ -114,7 +114,7 @@ namespace skyline::gpu::device {
|
|||||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvHostCtrlGpu::GetTpcMasks(IoctlBuffers &buffer) {
|
void NvHostCtrlGpu::GetTpcMasks(IoctlData &buffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 maskBufSize; // In
|
u32 maskBufSize; // In
|
||||||
u32 reserved[3]; // In
|
u32 reserved[3]; // In
|
||||||
@ -125,7 +125,7 @@ namespace skyline::gpu::device {
|
|||||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvHostCtrlGpu::GetActiveSlotMask(IoctlBuffers &buffer) {
|
void NvHostCtrlGpu::GetActiveSlotMask(IoctlData &buffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 slot; // Out
|
u32 slot; // Out
|
||||||
u32 mask; // Out
|
u32 mask; // Out
|
||||||
|
@ -13,26 +13,26 @@ namespace skyline::gpu::device {
|
|||||||
/**
|
/**
|
||||||
* @brief This returns a u32 GPU ZCULL Context Size (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE)
|
* @brief This returns a u32 GPU ZCULL Context Size (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE)
|
||||||
*/
|
*/
|
||||||
void ZCullGetCtxSize(IoctlBuffers &buffer);
|
void ZCullGetCtxSize(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a the GPU ZCULL Information (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_INFO)
|
* @brief This returns a the GPU ZCULL Information (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_INFO)
|
||||||
*/
|
*/
|
||||||
void ZCullGetInfo(IoctlBuffers &buffer);
|
void ZCullGetInfo(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a struct with certain GPU characteristics (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_CHARACTERISTICS)
|
* @brief This returns a struct with certain GPU characteristics (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_CHARACTERISTICS)
|
||||||
*/
|
*/
|
||||||
void GetCharacteristics(IoctlBuffers &buffer);
|
void GetCharacteristics(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the TPC mask value for each GPC (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS)
|
* @brief This returns the TPC mask value for each GPC (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS)
|
||||||
*/
|
*/
|
||||||
void GetTpcMasks(IoctlBuffers &buffer);
|
void GetTpcMasks(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the mask value for a ZBC slot (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZBC_GET_ACTIVE_SLOT_MASK)
|
* @brief This returns the mask value for a ZBC slot (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZBC_GET_ACTIVE_SLOT_MASK)
|
||||||
*/
|
*/
|
||||||
void GetActiveSlotMask(IoctlBuffers &buffer);
|
void GetActiveSlotMask(IoctlData &buffer);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace skyline::gpu::device {
|
|||||||
{0xC008010E, NFUNC(NvMap::GetId)}
|
{0xC008010E, NFUNC(NvMap::GetId)}
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void NvMap::Create(IoctlBuffers &buffer) {
|
void NvMap::Create(IoctlData &buffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 size; // In
|
u32 size; // In
|
||||||
u32 handle; // Out
|
u32 handle; // Out
|
||||||
@ -24,7 +24,7 @@ namespace skyline::gpu::device {
|
|||||||
state.logger->Debug("Create: Input: Size: 0x{:X}, Output: Handle: 0x{:X}, Status: {}", data.size, data.handle, buffer.status);
|
state.logger->Debug("Create: Input: Size: 0x{:X}, Output: Handle: 0x{:X}, Status: {}", data.size, data.handle, buffer.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvMap::FromId(skyline::gpu::device::IoctlBuffers &buffer) {
|
void NvMap::FromId(skyline::gpu::device::IoctlData &buffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 id; // In
|
u32 id; // In
|
||||||
u32 handle; // Out
|
u32 handle; // Out
|
||||||
@ -44,7 +44,7 @@ namespace skyline::gpu::device {
|
|||||||
state.logger->Debug("FromId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status);
|
state.logger->Debug("FromId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvMap::Alloc(IoctlBuffers &buffer) {
|
void NvMap::Alloc(IoctlData &buffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 handle; // In
|
u32 handle; // In
|
||||||
u32 heapMask; // In
|
u32 heapMask; // In
|
||||||
@ -64,7 +64,7 @@ namespace skyline::gpu::device {
|
|||||||
state.logger->Debug("Alloc: Input: Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}, Output: Status: {}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.address, buffer.status);
|
state.logger->Debug("Alloc: Input: Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}, Output: Status: {}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.address, buffer.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvMap::Free(skyline::gpu::device::IoctlBuffers &buffer) {
|
void NvMap::Free(skyline::gpu::device::IoctlData &buffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 handle; // In
|
u32 handle; // In
|
||||||
u32 _pad0_;
|
u32 _pad0_;
|
||||||
@ -85,7 +85,7 @@ namespace skyline::gpu::device {
|
|||||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvMap::Param(IoctlBuffers &buffer) {
|
void NvMap::Param(IoctlData &buffer) {
|
||||||
enum class Parameter : u32 { Size = 1, Alignment = 2, Base = 3, HeapMask = 4, Kind = 5, Compr = 6 }; // https://android.googlesource.com/kernel/tegra/+/refs/heads/android-tegra-flounder-3.10-marshmallow/include/linux/nvmap.h#102
|
enum class Parameter : u32 { Size = 1, Alignment = 2, Base = 3, HeapMask = 4, Kind = 5, Compr = 6 }; // https://android.googlesource.com/kernel/tegra/+/refs/heads/android-tegra-flounder-3.10-marshmallow/include/linux/nvmap.h#102
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 handle; // In
|
u32 handle; // In
|
||||||
@ -128,7 +128,7 @@ namespace skyline::gpu::device {
|
|||||||
state.logger->Debug("Param: Input: Handle: 0x{:X}, Parameter: {}, Output: Result: 0x{:X}, Status: {}", data.handle, data.parameter, data.result, buffer.status);
|
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(skyline::gpu::device::IoctlBuffers &buffer) {
|
void NvMap::GetId(skyline::gpu::device::IoctlData &buffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 id; // Out
|
u32 id; // Out
|
||||||
u32 handle; // In
|
u32 handle; // In
|
||||||
|
@ -41,31 +41,31 @@ namespace skyline::gpu::device {
|
|||||||
/**
|
/**
|
||||||
* @brief This creates an NvMapObject and returns an handle to it (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_CREATE)
|
* @brief This creates an NvMapObject and returns an handle to it (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_CREATE)
|
||||||
*/
|
*/
|
||||||
void Create(IoctlBuffers &buffer);
|
void Create(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the handle of an NvMapObject from it's ID (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FROM_ID)
|
* @brief This returns the handle of an NvMapObject from it's ID (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FROM_ID)
|
||||||
*/
|
*/
|
||||||
void FromId(IoctlBuffers &buffer);
|
void FromId(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This allocates memory for an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_ALLOC)
|
* @brief This allocates memory for an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_ALLOC)
|
||||||
*/
|
*/
|
||||||
void Alloc(IoctlBuffers &buffer);
|
void Alloc(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This frees previously allocated memory (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FREE)
|
* @brief This frees previously allocated memory (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FREE)
|
||||||
*/
|
*/
|
||||||
void Free(IoctlBuffers &buffer);
|
void Free(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns a particular parameter from an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_PARAM)
|
* @brief This returns a particular parameter from an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_PARAM)
|
||||||
*/
|
*/
|
||||||
void Param(IoctlBuffers &buffer);
|
void Param(IoctlData &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the ID of an NvMapObject from it's handle (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_GET_ID)
|
* @brief This returns the ID of an NvMapObject from it's handle (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_GET_ID)
|
||||||
*/
|
*/
|
||||||
void GetId(IoctlBuffers &buffer);
|
void GetId(IoctlData &buffer);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace skyline::gpu {
|
|||||||
state.thisProcess->ReadMemory(dataBuffer.data(), nvBuffer->address + gbpBuffer.offset, gbpBuffer.size);
|
state.thisProcess->ReadMemory(dataBuffer.data(), nvBuffer->address + gbpBuffer.offset, gbpBuffer.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferQueue::WaitContext::WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, u64 address, u64 size) : thread(std::move(thread)), input(input), address(address), size(size) {}
|
BufferQueue::WaitContext::WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, kernel::ipc::OutputBuffer& buffer) : thread(std::move(thread)), input(input), buffer(buffer) {}
|
||||||
|
|
||||||
BufferQueue::DequeueOut::DequeueOut(u32 slot) : slot(slot), _unk0_(0x1), _unk1_(0x24) {}
|
BufferQueue::DequeueOut::DequeueOut(u32 slot) : slot(slot), _unk0_(0x1), _unk1_(0x24) {}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ namespace skyline::gpu {
|
|||||||
state.logger->Debug("RequestBuffer: Slot: {}", slot, sizeof(GbpBuffer));
|
state.logger->Debug("RequestBuffer: Slot: {}", slot, sizeof(GbpBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferQueue::DequeueBuffer(Parcel &in, Parcel &out, u64 address, u64 size) {
|
bool BufferQueue::DequeueBuffer(Parcel &in, Parcel &out, kernel::ipc::OutputBuffer& buffer) {
|
||||||
auto *data = reinterpret_cast<DequeueIn *>(in.data.data() + constant::TokenLength);
|
auto *data = reinterpret_cast<DequeueIn *>(in.data.data() + constant::TokenLength);
|
||||||
i64 slot{-1};
|
i64 slot{-1};
|
||||||
for (auto &buffer : queue) {
|
for (auto &buffer : queue) {
|
||||||
@ -60,7 +60,7 @@ namespace skyline::gpu {
|
|||||||
}
|
}
|
||||||
if (slot == -1) {
|
if (slot == -1) {
|
||||||
state.thisThread->Sleep();
|
state.thisThread->Sleep();
|
||||||
waitVec.emplace_back(state.thisThread, *data, address, size);
|
waitVec.emplace_back(state.thisThread, *data, buffer);
|
||||||
state.logger->Debug("DequeueBuffer: Width: {}, Height: {}, Format: {}, Usage: {}, Timestamps: {}, No Free Buffers", data->width, data->height, data->format, data->usage, data->timestamps);
|
state.logger->Debug("DequeueBuffer: Width: {}, Height: {}, Format: {}, Usage: {}, Timestamps: {}, No Free Buffers", data->width, data->height, data->format, data->usage, data->timestamps);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -130,12 +130,12 @@ namespace skyline::gpu {
|
|||||||
else {
|
else {
|
||||||
auto context = waitVec.begin();
|
auto context = waitVec.begin();
|
||||||
while (context != waitVec.end()) {
|
while (context != waitVec.end()) {
|
||||||
if (slot->resolution.width == context->input.width && slot->resolution.height == context->input.height && slot->gbpBuffer.format == context->input.format && slot->gbpBuffer.usage == context->input.usage) {
|
if (slot->resolution.width == context->input.width && slot->resolution.height == context->input.height && slot->gbpBuffer.usage == context->input.usage) {
|
||||||
context->thread->WakeUp();
|
context->thread->WakeUp();
|
||||||
gpu::Parcel out(state);
|
gpu::Parcel out(state);
|
||||||
DequeueOut output(slotNo);
|
DequeueOut output(slotNo);
|
||||||
out.WriteData(output);
|
out.WriteData(output);
|
||||||
out.WriteParcel(context->address, context->size, context->thread->pid);
|
out.WriteParcel(context->buffer, context->thread->pid);
|
||||||
slot->status = BufferStatus::Dequeued;
|
slot->status = BufferStatus::Dequeued;
|
||||||
waitVec.erase(context);
|
waitVec.erase(context);
|
||||||
break;
|
break;
|
||||||
|
@ -160,16 +160,14 @@ namespace skyline::gpu {
|
|||||||
struct WaitContext {
|
struct WaitContext {
|
||||||
std::shared_ptr<kernel::type::KThread> thread; //!< The thread that is waiting on a buffer
|
std::shared_ptr<kernel::type::KThread> thread; //!< The thread that is waiting on a buffer
|
||||||
DequeueIn input; //!< The input of DequeueBuffer
|
DequeueIn input; //!< The input of DequeueBuffer
|
||||||
u64 address; //!< The address of the parcel buffer
|
kernel::ipc::OutputBuffer buffer; //!< The output buffer to write the parcel into
|
||||||
u64 size; //!< The size of the parcel buffer
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param thread The thread that is waiting on a buffer
|
* @param thread The thread that is waiting on a buffer
|
||||||
* @param input The input of DequeueBuffer
|
* @param input The input of DequeueBuffer
|
||||||
* @param address The address of the parcel buffer
|
* @param buffer The output buffer to write the parcel into
|
||||||
* @param size The size of the parcel buffer
|
|
||||||
*/
|
*/
|
||||||
WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, u64 address, u64 size);
|
WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, kernel::ipc::OutputBuffer& buffer);
|
||||||
};
|
};
|
||||||
std::vector<WaitContext> waitVec; //!< A vector of shared pointers to threads waiting on a buffer
|
std::vector<WaitContext> waitVec; //!< A vector of shared pointers to threads waiting on a buffer
|
||||||
|
|
||||||
@ -189,11 +187,10 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This returns the slot of a free buffer
|
* @brief This returns the slot of a free buffer
|
||||||
* @param address The address of the parcel buffer
|
* @param buffer The output parcel buffer
|
||||||
* @param size The size of the parcel buffer
|
|
||||||
* @return If the process is waiting for a buffer or not
|
* @return If the process is waiting for a buffer or not
|
||||||
*/
|
*/
|
||||||
bool DequeueBuffer(Parcel &in, Parcel &out, u64 address, u64 size);
|
bool DequeueBuffer(Parcel &in, Parcel &out, kernel::ipc::OutputBuffer& buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This queues a buffer to be displayed
|
* @brief This queues a buffer to be displayed
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
#include <kernel/types/KProcess.h>
|
#include <kernel/types/KProcess.h>
|
||||||
|
|
||||||
namespace skyline::gpu {
|
namespace skyline::gpu {
|
||||||
Parcel::Parcel(kernel::ipc::BufferDescriptorABW *buffer, const DeviceState &state) : Parcel(buffer->Address(), buffer->Size(), state) {}
|
Parcel::Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state) : Parcel(buffer.address, buffer.size, state) {}
|
||||||
|
|
||||||
Parcel::Parcel(kernel::ipc::BufferDescriptorX *buffer, const DeviceState &state) : Parcel(buffer->Address(), buffer->size, state) {}
|
|
||||||
|
|
||||||
Parcel::Parcel(u64 address, u64 size, const DeviceState &state) : state(state) {
|
Parcel::Parcel(u64 address, u64 size, const DeviceState &state) : state(state) {
|
||||||
state.thisProcess->ReadMemory(&header, address, sizeof(ParcelHeader));
|
state.thisProcess->ReadMemory(&header, address, sizeof(ParcelHeader));
|
||||||
@ -19,12 +17,8 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
Parcel::Parcel(const DeviceState &state) : state(state) {}
|
Parcel::Parcel(const DeviceState &state) : state(state) {}
|
||||||
|
|
||||||
u64 Parcel::WriteParcel(kernel::ipc::BufferDescriptorABW *buffer, pid_t process) {
|
u64 Parcel::WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process) {
|
||||||
return WriteParcel(buffer->Address(), buffer->Size(), process);
|
return WriteParcel(buffer.address, buffer.size, process);
|
||||||
}
|
|
||||||
|
|
||||||
u64 Parcel::WriteParcel(kernel::ipc::BufferDescriptorC *buffer, pid_t process) {
|
|
||||||
return WriteParcel(buffer->address, buffer->size, process);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Parcel::WriteParcel(u64 address, u64 maxSize, pid_t process) {
|
u64 Parcel::WriteParcel(u64 address, u64 maxSize, pid_t process) {
|
||||||
|
@ -31,14 +31,7 @@ namespace skyline::gpu {
|
|||||||
* @param buffer The buffer that contains the parcel
|
* @param buffer The buffer that contains the parcel
|
||||||
* @param state The state of the device
|
* @param state The state of the device
|
||||||
*/
|
*/
|
||||||
Parcel(kernel::ipc::BufferDescriptorABW *buffer, const DeviceState &state);
|
Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This constructor fills in the Parcel object with data from a IPC buffer
|
|
||||||
* @param buffer The buffer that contains the parcel
|
|
||||||
* @param state The state of the device
|
|
||||||
*/
|
|
||||||
Parcel(kernel::ipc::BufferDescriptorX *buffer, const DeviceState &state);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This constructor fills in the Parcel object with data from a Parcel on a remote process
|
* @brief This constructor fills in the Parcel object with data from a Parcel on a remote process
|
||||||
@ -85,20 +78,12 @@ namespace skyline::gpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes the Parcel object into a particular B buffer on a process
|
* @brief Writes the Parcel object into a particular output buffer on a process
|
||||||
* @param buffer The buffer to write into
|
* @param buffer The buffer to write into
|
||||||
* @param process The process to write the Parcel to
|
* @param process The process to write the Parcel to
|
||||||
* @return The total size of the message
|
* @return The total size of the message
|
||||||
*/
|
*/
|
||||||
u64 WriteParcel(kernel::ipc::BufferDescriptorABW *buffer, pid_t process = 0);
|
u64 WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process = 0);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Writes the Parcel object into a particular C buffer on a process
|
|
||||||
* @param buffer The buffer to write into
|
|
||||||
* @param process The process to write the Parcel to
|
|
||||||
* @return The total size of the message
|
|
||||||
*/
|
|
||||||
u64 WriteParcel(kernel::ipc::BufferDescriptorC *buffer, pid_t process = 0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes the Parcel object into the process's memory
|
* @brief Writes the Parcel object into the process's memory
|
||||||
|
@ -2,6 +2,16 @@
|
|||||||
#include "types/KProcess.h"
|
#include "types/KProcess.h"
|
||||||
|
|
||||||
namespace skyline::kernel::ipc {
|
namespace skyline::kernel::ipc {
|
||||||
|
IpcBuffer::IpcBuffer(u64 address, size_t size, IpcBufferType type) : address(address), size(size), type(type) {}
|
||||||
|
|
||||||
|
InputBuffer::InputBuffer(kernel::ipc::BufferDescriptorX *xBuf) : IpcBuffer(xBuf->Address(), xBuf->size, IpcBufferType::X) {}
|
||||||
|
|
||||||
|
InputBuffer::InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type) : IpcBuffer(aBuf->Address(), aBuf->Size(), type) {}
|
||||||
|
|
||||||
|
OutputBuffer::OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type) : IpcBuffer(bBuf->Address(), bBuf->Size(), type) {}
|
||||||
|
|
||||||
|
OutputBuffer::OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf) : IpcBuffer(cBuf->address, cBuf->size, IpcBufferType::C) {}
|
||||||
|
|
||||||
IpcRequest::IpcRequest(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state), tls() {
|
IpcRequest::IpcRequest(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state), tls() {
|
||||||
u8 *currPtr = tls.data();
|
u8 *currPtr = tls.data();
|
||||||
state.thisProcess->ReadMemory(currPtr, state.thisThread->tls, constant::TlsIpcSize);
|
state.thisProcess->ReadMemory(currPtr, state.thisThread->tls, constant::TlsIpcSize);
|
||||||
@ -25,7 +35,7 @@ namespace skyline::kernel::ipc {
|
|||||||
for (uint index = 0; header->Xno > index; index++) {
|
for (uint index = 0; header->Xno > index; index++) {
|
||||||
auto bufX = reinterpret_cast<BufferDescriptorX *>(currPtr);
|
auto bufX = reinterpret_cast<BufferDescriptorX *>(currPtr);
|
||||||
if (bufX->Address()) {
|
if (bufX->Address()) {
|
||||||
vecBufX.push_back(bufX);
|
inputBuf.emplace_back(bufX);
|
||||||
state.logger->Debug("Buf X #{} AD: 0x{:X} SZ: 0x{:X} CTR: {}", index, u64(bufX->Address()), u16(bufX->size), u16(bufX->Counter()));
|
state.logger->Debug("Buf X #{} AD: 0x{:X} SZ: 0x{:X} CTR: {}", index, u64(bufX->Address()), u16(bufX->size), u16(bufX->Counter()));
|
||||||
}
|
}
|
||||||
currPtr += sizeof(BufferDescriptorX);
|
currPtr += sizeof(BufferDescriptorX);
|
||||||
@ -34,7 +44,7 @@ namespace skyline::kernel::ipc {
|
|||||||
for (uint index = 0; header->Ano > index; index++) {
|
for (uint index = 0; header->Ano > index; index++) {
|
||||||
auto bufA = reinterpret_cast<BufferDescriptorABW *>(currPtr);
|
auto bufA = reinterpret_cast<BufferDescriptorABW *>(currPtr);
|
||||||
if (bufA->Address()) {
|
if (bufA->Address()) {
|
||||||
vecBufA.push_back(bufA);
|
inputBuf.emplace_back(bufA);
|
||||||
state.logger->Debug("Buf A #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufA->Address()), u64(bufA->Size()));
|
state.logger->Debug("Buf A #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufA->Address()), u64(bufA->Size()));
|
||||||
}
|
}
|
||||||
currPtr += sizeof(BufferDescriptorABW);
|
currPtr += sizeof(BufferDescriptorABW);
|
||||||
@ -43,7 +53,7 @@ namespace skyline::kernel::ipc {
|
|||||||
for (uint index = 0; header->Bno > index; index++) {
|
for (uint index = 0; header->Bno > index; index++) {
|
||||||
auto bufB = reinterpret_cast<BufferDescriptorABW *>(currPtr);
|
auto bufB = reinterpret_cast<BufferDescriptorABW *>(currPtr);
|
||||||
if (bufB->Address()) {
|
if (bufB->Address()) {
|
||||||
vecBufB.push_back(bufB);
|
outputBuf.emplace_back(bufB);
|
||||||
state.logger->Debug("Buf B #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufB->Address()), u64(bufB->Size()));
|
state.logger->Debug("Buf B #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufB->Address()), u64(bufB->Size()));
|
||||||
}
|
}
|
||||||
currPtr += sizeof(BufferDescriptorABW);
|
currPtr += sizeof(BufferDescriptorABW);
|
||||||
@ -52,7 +62,8 @@ namespace skyline::kernel::ipc {
|
|||||||
for (uint index = 0; header->Wno > index; index++) {
|
for (uint index = 0; header->Wno > index; index++) {
|
||||||
auto bufW = reinterpret_cast<BufferDescriptorABW *>(currPtr);
|
auto bufW = reinterpret_cast<BufferDescriptorABW *>(currPtr);
|
||||||
if (bufW->Address()) {
|
if (bufW->Address()) {
|
||||||
vecBufW.push_back(bufW);
|
inputBuf.emplace_back(bufW, IpcBufferType::W);
|
||||||
|
outputBuf.emplace_back(bufW, IpcBufferType::W);
|
||||||
state.logger->Debug("Buf W #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufW->Address()), u16(bufW->Size()));
|
state.logger->Debug("Buf W #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufW->Address()), u16(bufW->Size()));
|
||||||
}
|
}
|
||||||
currPtr += sizeof(BufferDescriptorABW);
|
currPtr += sizeof(BufferDescriptorABW);
|
||||||
@ -85,6 +96,8 @@ namespace skyline::kernel::ipc {
|
|||||||
currPtr += cmdArgSz;
|
currPtr += cmdArgSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
payloadOffset = cmdArg;
|
||||||
|
|
||||||
if (payload->magic != constant::SfciMagic && header->type != CommandType::Control)
|
if (payload->magic != constant::SfciMagic && header->type != CommandType::Control)
|
||||||
state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
|
state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
|
||||||
|
|
||||||
@ -92,13 +105,15 @@ namespace skyline::kernel::ipc {
|
|||||||
|
|
||||||
if (header->cFlag == BufferCFlag::SingleDescriptor) {
|
if (header->cFlag == BufferCFlag::SingleDescriptor) {
|
||||||
auto bufC = reinterpret_cast<BufferDescriptorC *>(currPtr);
|
auto bufC = reinterpret_cast<BufferDescriptorC *>(currPtr);
|
||||||
vecBufC.push_back(bufC);
|
if (bufC->address) {
|
||||||
|
outputBuf.emplace_back(bufC);
|
||||||
state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size));
|
state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size));
|
||||||
|
}
|
||||||
} else if (header->cFlag > BufferCFlag::SingleDescriptor) {
|
} else if (header->cFlag > BufferCFlag::SingleDescriptor) {
|
||||||
for (uint index = 0; (static_cast<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present
|
for (uint index = 0; (static_cast<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present
|
||||||
auto bufC = reinterpret_cast<BufferDescriptorC *>(currPtr);
|
auto bufC = reinterpret_cast<BufferDescriptorC *>(currPtr);
|
||||||
if (bufC->address) {
|
if (bufC->address) {
|
||||||
vecBufC.push_back(bufC);
|
outputBuf.emplace_back(bufC);
|
||||||
state.logger->Debug("Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufC->address), u16(bufC->size));
|
state.logger->Debug("Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufC->address), u16(bufC->size));
|
||||||
}
|
}
|
||||||
currPtr += sizeof(BufferDescriptorC);
|
currPtr += sizeof(BufferDescriptorC);
|
||||||
@ -106,7 +121,7 @@ namespace skyline::kernel::ipc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (header->type == CommandType::Request) {
|
if (header->type == CommandType::Request) {
|
||||||
state.logger->Debug("Header: X No: {}, A No: {}, B No: {}, W No: {}, C No: {}, Raw Size: {}", u8(header->Xno), u8(header->Ano), u8(header->Bno), u8(header->Wno), u8(vecBufC.size()), u64(cmdArgSz));
|
state.logger->Debug("Header: Input No: {}, Output No: {}, Raw Size: {}", inputBuf.size(), outputBuf.size(), u64(cmdArgSz));
|
||||||
if (header->handleDesc)
|
if (header->handleDesc)
|
||||||
state.logger->Debug("Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", bool(handleDesc->sendPid), u32(handleDesc->copyCount), u32(handleDesc->moveCount));
|
state.logger->Debug("Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", bool(handleDesc->sendPid), u32(handleDesc->copyCount), u32(handleDesc->moveCount));
|
||||||
if (isDomain)
|
if (isDomain)
|
||||||
@ -117,7 +132,7 @@ namespace skyline::kernel::ipc {
|
|||||||
|
|
||||||
IpcResponse::IpcResponse(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state) {}
|
IpcResponse::IpcResponse(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state) {}
|
||||||
|
|
||||||
void IpcResponse::WriteTls() {
|
void IpcResponse::WriteResponse() {
|
||||||
std::array<u8, constant::TlsIpcSize> tls{};
|
std::array<u8, constant::TlsIpcSize> tls{};
|
||||||
u8 *currPtr = tls.data();
|
u8 *currPtr = tls.data();
|
||||||
auto header = reinterpret_cast<CommandHeader *>(currPtr);
|
auto header = reinterpret_cast<CommandHeader *>(currPtr);
|
||||||
|
@ -168,12 +168,70 @@ namespace skyline::kernel::ipc {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(BufferDescriptorC) == 8);
|
static_assert(sizeof(BufferDescriptorC) == 8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This enumerates the types of IPC buffers
|
||||||
|
*/
|
||||||
|
enum class IpcBufferType {
|
||||||
|
X, //!< This is a type-X buffer
|
||||||
|
A, //!< This is a type-A buffer
|
||||||
|
B, //!< This is a type-B buffer
|
||||||
|
W, //!< This is a type-W buffer
|
||||||
|
C //!< This is a type-C buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Describes a buffer by holding the address and size
|
||||||
|
*/
|
||||||
|
struct IpcBuffer {
|
||||||
|
u64 address; //!< The address of the buffer
|
||||||
|
size_t size; //!< The size of the buffer
|
||||||
|
IpcBufferType type; //!< The type of the buffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param address The address of the buffer
|
||||||
|
* @param size The size of the buffer
|
||||||
|
* @param type The type of the buffer
|
||||||
|
*/
|
||||||
|
IpcBuffer(u64 address, size_t size, IpcBufferType type);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This holds an input IPC buffer
|
||||||
|
*/
|
||||||
|
struct InputBuffer : public IpcBuffer {
|
||||||
|
/**
|
||||||
|
* @param aBuf The X Buffer Descriptor that has contains the input data
|
||||||
|
*/
|
||||||
|
InputBuffer(kernel::ipc::BufferDescriptorX *xBuf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param aBuf The A or W Buffer Descriptor that has contains the input data
|
||||||
|
*/
|
||||||
|
InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type = IpcBufferType::A);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This holds an output IPC buffer
|
||||||
|
*/
|
||||||
|
struct OutputBuffer : public IpcBuffer {
|
||||||
|
/**
|
||||||
|
* @param bBuf The B or W Buffer Descriptor that has to be outputted to
|
||||||
|
*/
|
||||||
|
OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type = IpcBufferType::B);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cBuf The C Buffer Descriptor that has to be outputted to
|
||||||
|
*/
|
||||||
|
OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class encapsulates an IPC Request (https://switchbrew.org/wiki/IPC_Marshalling)
|
* @brief This class encapsulates an IPC Request (https://switchbrew.org/wiki/IPC_Marshalling)
|
||||||
*/
|
*/
|
||||||
class IpcRequest {
|
class IpcRequest {
|
||||||
private:
|
private:
|
||||||
const DeviceState &state; //!< The state of the device
|
const DeviceState &state; //!< The state of the device
|
||||||
|
u8 *payloadOffset; //!< This is the offset of the data read from the payload
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::array<u8, constant::TlsIpcSize> tls; //!< A static-sized array where TLS data is actually copied to
|
std::array<u8, constant::TlsIpcSize> tls; //!< A static-sized array where TLS data is actually copied to
|
||||||
@ -187,17 +245,34 @@ namespace skyline::kernel::ipc {
|
|||||||
std::vector<handle_t> copyHandles; //!< A vector of handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles)
|
std::vector<handle_t> copyHandles; //!< A vector of handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles)
|
||||||
std::vector<handle_t> moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied
|
std::vector<handle_t> moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied
|
||||||
std::vector<handle_t> domainObjects; //!< A vector of all input domain objects
|
std::vector<handle_t> domainObjects; //!< A vector of all input domain objects
|
||||||
std::vector<BufferDescriptorX *> vecBufX; //!< This is a vector of pointers to X Buffer Descriptors
|
std::vector<InputBuffer> inputBuf; //!< This is a vector of input buffers
|
||||||
std::vector<BufferDescriptorABW *> vecBufA; //!< This is a vector of pointers to A Buffer Descriptors
|
std::vector<OutputBuffer> outputBuf; //!< This is a vector of output buffers
|
||||||
std::vector<BufferDescriptorABW *> vecBufB; //!< This is a vector of pointers to B Buffer Descriptors
|
|
||||||
std::vector<BufferDescriptorABW *> vecBufW; //!< This is a vector of pointers to W Buffer Descriptors
|
|
||||||
std::vector<BufferDescriptorC *> vecBufC; //!< This is a vector of pointers to C Buffer Descriptors
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isDomain If the following request is a domain request
|
* @param isDomain If the following request is a domain request
|
||||||
* @param state The state of the device
|
* @param state The state of the device
|
||||||
*/
|
*/
|
||||||
IpcRequest(bool isDomain, const DeviceState &state);
|
IpcRequest(bool isDomain, const DeviceState &state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This returns a reference to an item from the top of the payload
|
||||||
|
* @tparam ValueType The type of the object to read
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
inline ValueType& Pop() {
|
||||||
|
ValueType& value = *reinterpret_cast<ValueType*>(payloadOffset);
|
||||||
|
payloadOffset += sizeof(ValueType);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This skips an object to pop off the top
|
||||||
|
* @tparam ValueType The type of the object to skip
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
inline void Skip() {
|
||||||
|
payloadOffset += sizeof(ValueType);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -225,10 +300,10 @@ namespace skyline::kernel::ipc {
|
|||||||
/**
|
/**
|
||||||
* @brief Writes an object to the payload
|
* @brief Writes an object to the payload
|
||||||
* @tparam ValueType The type of the object to write
|
* @tparam ValueType The type of the object to write
|
||||||
* @param value The object to be written
|
* @param value A reference to the object to be written
|
||||||
*/
|
*/
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void WriteValue(const ValueType &value) {
|
inline void Push(const ValueType &value) {
|
||||||
argVec.reserve(argVec.size() + sizeof(ValueType));
|
argVec.reserve(argVec.size() + sizeof(ValueType));
|
||||||
auto item = reinterpret_cast<const u8 *>(&value);
|
auto item = reinterpret_cast<const u8 *>(&value);
|
||||||
for (uint index = 0; sizeof(ValueType) > index; index++) {
|
for (uint index = 0; sizeof(ValueType) > index; index++) {
|
||||||
@ -240,6 +315,6 @@ namespace skyline::kernel::ipc {
|
|||||||
/**
|
/**
|
||||||
* @brief Writes this IpcResponse object's contents into TLS
|
* @brief Writes this IpcResponse object's contents into TLS
|
||||||
*/
|
*/
|
||||||
void WriteTls();
|
void WriteResponse();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -460,6 +460,8 @@ namespace skyline::kernel::svc {
|
|||||||
void OutputDebugString(DeviceState &state) {
|
void OutputDebugString(DeviceState &state) {
|
||||||
std::string debug(state.nce->GetRegister(Xreg::X1), '\0');
|
std::string debug(state.nce->GetRegister(Xreg::X1), '\0');
|
||||||
state.os->thisProcess->ReadMemory(debug.data(), state.nce->GetRegister(Xreg::X0), state.nce->GetRegister(Xreg::X1));
|
state.os->thisProcess->ReadMemory(debug.data(), state.nce->GetRegister(Xreg::X0), state.nce->GetRegister(Xreg::X1));
|
||||||
|
if(debug.back() == '\n')
|
||||||
|
debug.pop_back();
|
||||||
state.logger->Info("Debug Output: {}", debug);
|
state.logger->Info("Debug Output: {}", debug);
|
||||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,6 @@
|
|||||||
#include <nce.h>
|
#include <nce.h>
|
||||||
#include <os.h>
|
#include <os.h>
|
||||||
|
|
||||||
constexpr const char *ASHMEM_NAME_DEF = "dev/ashmem";
|
|
||||||
constexpr int ASHMEM_SET_SIZE = 0x40087703;
|
|
||||||
|
|
||||||
namespace skyline::kernel::type {
|
namespace skyline::kernel::type {
|
||||||
u64 MapTransferFunc(u64 address, size_t size, u64 perms) {
|
u64 MapTransferFunc(u64 address, size_t size, u64 perms) {
|
||||||
return reinterpret_cast<u64>(mmap(reinterpret_cast<void *>(address), size, static_cast<int>(perms), MAP_ANONYMOUS | MAP_PRIVATE | ((address) ? MAP_FIXED : 0), -1, 0)); // NOLINT(hicpp-signed-bitwise)
|
return reinterpret_cast<u64>(mmap(reinterpret_cast<void *>(address), size, static_cast<int>(perms), MAP_ANONYMOUS | MAP_PRIVATE | ((address) ? MAP_FIXED : 0), -1, 0)); // NOLINT(hicpp-signed-bitwise)
|
||||||
|
@ -30,20 +30,20 @@ namespace skyline::service::am {
|
|||||||
response.errorCode = constant::status::NoMessages;
|
response.errorCode = constant::status::NoMessages;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
response.WriteValue<u32>(static_cast<u32>(messageQueue.front()));
|
response.Push<u32>(static_cast<u32>(messageQueue.front()));
|
||||||
messageQueue.pop();
|
messageQueue.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void ICommonStateGetter::GetCurrentFocusState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u8>(static_cast<u8>(focusState));
|
response.Push<u8>(static_cast<u8>(focusState));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void ICommonStateGetter::GetOperationMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u8>(static_cast<u8>(operationMode));
|
response.Push<u8>(static_cast<u8>(operationMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void ICommonStateGetter::GetPerformanceMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u32>(static_cast<u32>(operationMode));
|
response.Push<u32>(static_cast<u32>(operationMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetDefaultDisplayResolution(type::KSession& session, ipc::IpcRequest& request, ipc::IpcResponse& response) {
|
void ICommonStateGetter::GetDefaultDisplayResolution(type::KSession& session, ipc::IpcRequest& request, ipc::IpcResponse& response) {
|
||||||
@ -77,7 +77,7 @@ namespace skyline::service::am {
|
|||||||
if (state.gpu->layerStatus == gpu::LayerStatus::Initialized)
|
if (state.gpu->layerStatus == gpu::LayerStatus::Initialized)
|
||||||
throw exception("The application is creating more than one layer");
|
throw exception("The application is creating more than one layer");
|
||||||
state.gpu->layerStatus = gpu::LayerStatus::Initialized;
|
state.gpu->layerStatus = gpu::LayerStatus::Initialized;
|
||||||
response.WriteValue<u64>(0);
|
response.Push<u64>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
IWindowController::IWindowController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IWindowController, {
|
IWindowController::IWindowController(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IWindowController, {
|
||||||
@ -86,7 +86,7 @@ namespace skyline::service::am {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IWindowController::GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IWindowController::GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue(static_cast<u64>(state.thisProcess->mainThread));
|
response.Push(static_cast<u64>(state.thisProcess->mainThread));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWindowController::AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
void IWindowController::AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
||||||
@ -105,7 +105,7 @@ namespace skyline::service::am {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IApplicationFunctions::NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IApplicationFunctions::NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u8>(1);
|
response.Push<u8>(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDebugFunctions::IDebugFunctions(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IDebugFunctions, {
|
IDebugFunctions::IDebugFunctions(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::am_IDebugFunctions, {
|
||||||
|
@ -15,16 +15,14 @@ namespace skyline::service::apm {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ISession::SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void ISession::SetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
auto mode = request.Pop<u32>();
|
||||||
u32 mode;
|
auto config = request.Pop<u32>();
|
||||||
u32 config;
|
performanceConfig[mode] = config;
|
||||||
} *performance = reinterpret_cast<InputStruct *>(request.cmdArg);
|
state.logger->Info("SetPerformanceConfiguration called with 0x{:X} ({})", config, mode ? "Docked" : "Handheld");
|
||||||
performanceConfig[performance->mode] = performance->config;
|
|
||||||
state.logger->Info("SetPerformanceConfiguration called with 0x{:X} ({})", performance->config, performance->mode ? "Docked" : "Handheld");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISession::GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void ISession::GetPerformanceConfiguration(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
u32 performanceMode = *reinterpret_cast<u32 *>(request.cmdArg);
|
u32 performanceMode = request.Pop<u32>();
|
||||||
response.WriteValue<u32>(performanceConfig[performanceMode]);
|
response.Push<u32>(performanceConfig[performanceMode]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,20 +30,16 @@ namespace skyline::service::hid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void hid::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void hid::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
auto styleSet = request.Pop<StyleSet>();
|
||||||
u32 styleSet;
|
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>
|
||||||
u64 appletUserId;
|
(styleSet.joyconRight), static_cast<bool>(styleSet.gamecube), static_cast<bool>(styleSet.pokeball), static_cast<bool>(styleSet.nes), static_cast<bool>(styleSet.nesHandheld), static_cast<bool>(styleSet.snes));
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
styleSet = *reinterpret_cast<StyleSet *>(&input->styleSet);
|
|
||||||
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->pokeball), static_cast<bool>(styleSet->nes), static_cast<bool>(styleSet->nesHandheld), static_cast<bool>(styleSet->snes));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hid::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void hid::SetSupportedNpadIdType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
const auto &buffer = request.vecBufX[0];
|
const auto &buffer = request.inputBuf.at(0);
|
||||||
uint numId = buffer->size / sizeof(NpadId);
|
size_t numId = buffer.size / sizeof(NpadId);
|
||||||
u64 address = buffer->Address();
|
u64 address = buffer.address;
|
||||||
for (uint i = 0; i < numId; i++) {
|
for (size_t i = 0; i < numId; i++) {
|
||||||
auto id = state.thisProcess->ReadMemory<NpadId>(address);
|
auto id = state.thisProcess->ReadMemory<NpadId>(address);
|
||||||
deviceMap[id] = JoyConDevice(id);
|
deviceMap[id] = JoyConDevice(id);
|
||||||
address += sizeof(NpadId);
|
address += sizeof(NpadId);
|
||||||
@ -53,36 +49,21 @@ namespace skyline::service::hid {
|
|||||||
void hid::ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
void hid::ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
||||||
|
|
||||||
void hid::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void hid::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
deviceMap[request.Pop<NpadId>()].assignment = JoyConAssignment::Single;
|
||||||
NpadId controllerId;
|
|
||||||
u64 appletUserId;
|
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
deviceMap[input->controllerId].assignment = JoyConAssignment::Single;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hid::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void hid::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
orientation = request.Pop<JoyConOrientation>();
|
||||||
u64 appletUserId;
|
|
||||||
JoyConOrientation orientation;
|
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
orientation = input->orientation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hid::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void hid::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
auto controllerId = request.Pop<NpadId>();
|
||||||
NpadId controllerId;
|
auto appletUserId = request.Pop<u64>();
|
||||||
u64 appletUserId;
|
deviceMap[controllerId].assignment = JoyConAssignment::Single;
|
||||||
JoyConSide joyDeviceType;
|
deviceMap[controllerId].side = request.Pop<JoyConSide>();
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
deviceMap[input->controllerId].assignment = JoyConAssignment::Single;
|
|
||||||
deviceMap[input->controllerId].side = input->joyDeviceType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hid::SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void hid::SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
deviceMap[request.Pop<NpadId>()].assignment = JoyConAssignment::Dual;
|
||||||
NpadId controllerType;
|
|
||||||
u64 appletUserId;
|
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
deviceMap[input->controllerType].assignment = JoyConAssignment::Dual;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,43 +12,39 @@ namespace skyline::service::nvdrv {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void nvdrv::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void nvdrv::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto aBuf = request.vecBufA[0];
|
auto buffer = request.inputBuf.at(0);
|
||||||
std::string path(aBuf->Size(), '\0');
|
std::string path(buffer.size, '\0');
|
||||||
state.thisProcess->ReadMemory(path.data(), aBuf->Address(), aBuf->Size());
|
state.thisProcess->ReadMemory(path.data(), buffer.address, buffer.size);
|
||||||
response.WriteValue<u32>(state.gpu->OpenDevice(path));
|
response.Push<u32>(state.gpu->OpenDevice(path));
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvdrv::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void nvdrv::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
auto fd = request.Pop<u32>();
|
||||||
u32 fd;
|
auto cmd = request.Pop<u32>();
|
||||||
u32 cmd;
|
state.gpu->Ioctl(fd, cmd, request, response);
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
state.gpu->Ioctl(input->fd, input->cmd, request, response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvdrv::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void nvdrv::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
u32 fd = *reinterpret_cast<u32 *>(request.cmdArg);
|
u32 fd = *reinterpret_cast<u32 *>(request.cmdArg);
|
||||||
state.gpu->CloseDevice(fd);
|
state.gpu->CloseDevice(fd);
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvdrv::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void nvdrv::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvdrv::QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void nvdrv::QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
auto fd = request.Pop<u32>();
|
||||||
u32 fd;
|
auto eventId = request.Pop<u32>();
|
||||||
u32 eventId;
|
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
auto event = std::make_shared<type::KEvent>(state);
|
auto event = std::make_shared<type::KEvent>(state);
|
||||||
auto handle = state.thisProcess->InsertItem<type::KEvent>(event);
|
auto handle = state.thisProcess->InsertItem<type::KEvent>(event);
|
||||||
state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", input->fd, input->eventId, handle);
|
state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", fd, eventId, handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvdrv::SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void nvdrv::SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,36 +11,25 @@ namespace skyline::service::nvnflinger {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void dispdrv::TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void dispdrv::TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
auto layerId = request.Pop<u32>();
|
||||||
u32 layerId;
|
auto code = request.Pop<TransactionCode>();
|
||||||
TransactionCode code;
|
gpu::Parcel in(request.inputBuf.at(0), state);
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
std::shared_ptr<gpu::Parcel> in{};
|
|
||||||
if (request.vecBufA.empty())
|
|
||||||
in = std::make_shared<gpu::Parcel>(request.vecBufX[0], state);
|
|
||||||
else
|
|
||||||
in = std::make_shared<gpu::Parcel>(request.vecBufA[0], state);
|
|
||||||
gpu::Parcel out(state);
|
gpu::Parcel out(state);
|
||||||
state.logger->Debug("TransactParcel: Layer ID: {}, Code: {}", input->layerId, input->code);
|
state.logger->Debug("TransactParcel: Layer ID: {}, Code: {}", layerId, code);
|
||||||
switch (input->code) {
|
switch (code) {
|
||||||
case TransactionCode::RequestBuffer:
|
case TransactionCode::RequestBuffer:
|
||||||
state.gpu->bufferQueue.RequestBuffer(*in, out);
|
state.gpu->bufferQueue.RequestBuffer(in, out);
|
||||||
break;
|
break;
|
||||||
case TransactionCode::DequeueBuffer: {
|
case TransactionCode::DequeueBuffer: {
|
||||||
if (request.vecBufA.empty()) {
|
if (state.gpu->bufferQueue.DequeueBuffer(in, out, request.outputBuf.at(0)))
|
||||||
if (state.gpu->bufferQueue.DequeueBuffer(*in, out, request.vecBufC[0]->address, request.vecBufC[0]->size))
|
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
if (state.gpu->bufferQueue.DequeueBuffer(*in, out, request.vecBufB[0]->Address(), request.vecBufB[0]->Size()))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TransactionCode::QueueBuffer:
|
case TransactionCode::QueueBuffer:
|
||||||
state.gpu->bufferQueue.QueueBuffer(*in, out);
|
state.gpu->bufferQueue.QueueBuffer(in, out);
|
||||||
break;
|
break;
|
||||||
case TransactionCode::CancelBuffer:
|
case TransactionCode::CancelBuffer:
|
||||||
state.gpu->bufferQueue.CancelBuffer(*in);
|
state.gpu->bufferQueue.CancelBuffer(in);
|
||||||
break;
|
break;
|
||||||
case TransactionCode::Query:
|
case TransactionCode::Query:
|
||||||
out.WriteData<u64>(0);
|
out.WriteData<u64>(0);
|
||||||
@ -59,30 +48,25 @@ namespace skyline::service::nvnflinger {
|
|||||||
case TransactionCode::Disconnect:
|
case TransactionCode::Disconnect:
|
||||||
break;
|
break;
|
||||||
case TransactionCode::SetPreallocatedBuffer:
|
case TransactionCode::SetPreallocatedBuffer:
|
||||||
state.gpu->bufferQueue.SetPreallocatedBuffer(*in);
|
state.gpu->bufferQueue.SetPreallocatedBuffer(in);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw exception("An unimplemented transaction was called: {}", static_cast<u32>(input->code));
|
throw exception("An unimplemented transaction was called: {}", static_cast<u32>(code));
|
||||||
}
|
}
|
||||||
if (request.vecBufA.empty())
|
out.WriteParcel(request.outputBuf.at(0));
|
||||||
out.WriteParcel(request.vecBufC[0]);
|
}
|
||||||
else
|
|
||||||
out.WriteParcel(request.vecBufB[0]);
|
void dispdrv::AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
request.Skip<u32>();
|
||||||
|
auto addVal = request.Pop<i32>();
|
||||||
|
auto type = request.Pop<i32>();
|
||||||
|
state.logger->Debug("Reference Change: {} {} reference", addVal, type ? "strong" : "weak");
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispdrv::GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void dispdrv::GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
handle_t handle = state.thisProcess->InsertItem(state.gpu->bufferEvent);
|
handle_t handle = state.thisProcess->InsertItem(state.gpu->bufferEvent);
|
||||||
state.logger->Debug("BufferEvent Handle: 0x{:X}", handle);
|
state.logger->Debug("BufferEvent Handle: 0x{:X}", handle);
|
||||||
response.copyHandles.push_back(handle);
|
response.copyHandles.push_back(handle);
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
|
||||||
|
|
||||||
void dispdrv::AdjustRefcount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
|
||||||
struct InputStruct {
|
|
||||||
u32 layerId;
|
|
||||||
i32 addVal;
|
|
||||||
i32 type;
|
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
state.logger->Debug("Reference Change: {} {} reference", input->addVal, input->type ? "strong" : "weak");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,14 +50,14 @@ namespace skyline::service::nvnflinger {
|
|||||||
*/
|
*/
|
||||||
void TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
void 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#GetNativeHandle)
|
|
||||||
*/
|
|
||||||
void GetNativeHandle(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);
|
void 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)
|
||||||
|
*/
|
||||||
|
void GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ namespace skyline::service {
|
|||||||
} else
|
} else
|
||||||
session->serviceObject->HandleRequest(*session, request, response);
|
session->serviceObject->HandleRequest(*session, request, response);
|
||||||
if (!response.nWrite)
|
if (!response.nWrite)
|
||||||
response.WriteTls();
|
response.WriteResponse();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ipc::CommandType::Control:
|
case ipc::CommandType::Control:
|
||||||
@ -207,19 +207,19 @@ namespace skyline::service {
|
|||||||
state.logger->Debug("Control IPC Message: 0x{:X}", request.payload->value);
|
state.logger->Debug("Control IPC Message: 0x{:X}", request.payload->value);
|
||||||
switch (static_cast<ipc::ControlCommand>(request.payload->value)) {
|
switch (static_cast<ipc::ControlCommand>(request.payload->value)) {
|
||||||
case ipc::ControlCommand::ConvertCurrentObjectToDomain:
|
case ipc::ControlCommand::ConvertCurrentObjectToDomain:
|
||||||
response.WriteValue(session->ConvertDomain());
|
response.Push(session->ConvertDomain());
|
||||||
break;
|
break;
|
||||||
case ipc::ControlCommand::CloneCurrentObject:
|
case ipc::ControlCommand::CloneCurrentObject:
|
||||||
case ipc::ControlCommand::CloneCurrentObjectEx:
|
case ipc::ControlCommand::CloneCurrentObjectEx:
|
||||||
response.WriteValue(state.thisProcess->InsertItem(session));
|
response.Push(state.thisProcess->InsertItem(session));
|
||||||
break;
|
break;
|
||||||
case ipc::ControlCommand::QueryPointerBufferSize:
|
case ipc::ControlCommand::QueryPointerBufferSize:
|
||||||
response.WriteValue<u32>(0x1000);
|
response.Push<u32>(0x1000);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw exception("Unknown Control Command: {}", request.payload->value);
|
throw exception("Unknown Control Command: {}", request.payload->value);
|
||||||
}
|
}
|
||||||
response.WriteTls();
|
response.WriteResponse();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ipc::CommandType::Close:
|
case ipc::CommandType::Close:
|
||||||
|
@ -6,6 +6,6 @@ namespace skyline::service::set {
|
|||||||
|
|
||||||
void sys::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void sys::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
SysVerTitle title{.minor=9, .major=0, .micro=0, .revMajor=4, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
SysVerTitle title{.minor=9, .major=0, .micro=0, .revMajor=4, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
||||||
state.thisProcess->WriteMemory(title, request.vecBufC[0]->address);
|
state.thisProcess->WriteMemory(title, request.outputBuf.at(0).address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ namespace skyline::service::time {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ISystemClock::GetCurrentTime(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void ISystemClock::GetCurrentTime(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u64>(static_cast<u64>(std::time(nullptr)));
|
response.Push<u64>(static_cast<u64>(std::time(nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ITimeZoneService::ITimeZoneService(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::time_ITimeZoneService, {
|
ITimeZoneService::ITimeZoneService(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, false, Service::time_ITimeZoneService, {
|
||||||
@ -46,7 +46,7 @@ namespace skyline::service::time {
|
|||||||
.minute = static_cast<u8>(calender.tm_min),
|
.minute = static_cast<u8>(calender.tm_min),
|
||||||
.second = static_cast<u8>(calender.tm_sec)
|
.second = static_cast<u8>(calender.tm_sec)
|
||||||
};
|
};
|
||||||
response.WriteValue(calendarTime);
|
response.Push(calendarTime);
|
||||||
CalendarAdditionalInfo calendarInfo{
|
CalendarAdditionalInfo calendarInfo{
|
||||||
.day_week = static_cast<u32>(calender.tm_wday),
|
.day_week = static_cast<u32>(calender.tm_wday),
|
||||||
.day_month = static_cast<u32>(calender.tm_mday),
|
.day_month = static_cast<u32>(calender.tm_mday),
|
||||||
@ -54,6 +54,6 @@ namespace skyline::service::time {
|
|||||||
.dst = static_cast<i32>(calender.tm_isdst),
|
.dst = static_cast<i32>(calender.tm_isdst),
|
||||||
.utc_rel = static_cast<u32>(calender.tm_gmtoff)
|
.utc_rel = static_cast<u32>(calender.tm_gmtoff)
|
||||||
};
|
};
|
||||||
response.WriteValue(calendarInfo);
|
response.Push(calendarInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace skyline::service::vi {
|
|||||||
|
|
||||||
void IDisplayService::CreateStrayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IDisplayService::CreateStrayLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
state.logger->Debug("Creating Stray Layer");
|
state.logger->Debug("Creating Stray Layer");
|
||||||
response.WriteValue<u64>(0); // There's only one layer
|
response.Push<u64>(0); // There's only one layer
|
||||||
gpu::Parcel parcel(state);
|
gpu::Parcel parcel(state);
|
||||||
LayerParcel data{
|
LayerParcel data{
|
||||||
.type = 0x20,
|
.type = 0x20,
|
||||||
@ -25,7 +25,7 @@ namespace skyline::service::vi {
|
|||||||
.string = "dispdrv"
|
.string = "dispdrv"
|
||||||
};
|
};
|
||||||
parcel.WriteData(data);
|
parcel.WriteData(data);
|
||||||
response.WriteValue<u64>(parcel.WriteParcel(request.vecBufB[0]));
|
response.Push<u64>(parcel.WriteParcel(request.outputBuf.at(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
IApplicationDisplayService::IApplicationDisplayService(const DeviceState &state, ServiceManager &manager) : IDisplayService(state, manager, Service::vi_IApplicationDisplayService, {
|
IApplicationDisplayService::IApplicationDisplayService(const DeviceState &state, ServiceManager &manager) : IDisplayService(state, manager, Service::vi_IApplicationDisplayService, {
|
||||||
@ -61,7 +61,7 @@ namespace skyline::service::vi {
|
|||||||
std::string displayName(reinterpret_cast<char *>(request.cmdArg));
|
std::string displayName(reinterpret_cast<char *>(request.cmdArg));
|
||||||
state.logger->Debug("Setting display as: {}", displayName);
|
state.logger->Debug("Setting display as: {}", displayName);
|
||||||
state.gpu->SetDisplay(displayName);
|
state.gpu->SetDisplay(displayName);
|
||||||
response.WriteValue<u64>(0); // There's only one display
|
response.Push<u64>(0); // There's only one display
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationDisplayService::CloseDisplay(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IApplicationDisplayService::CloseDisplay(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
@ -74,9 +74,9 @@ namespace skyline::service::vi {
|
|||||||
char displayName[0x40];
|
char displayName[0x40];
|
||||||
u64 layerId;
|
u64 layerId;
|
||||||
u64 userId;
|
u64 userId;
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
} input = request.Pop<InputStruct>();
|
||||||
state.logger->Debug("Opening Layer: Display Name: {}, Layer ID: {}, User ID: {}", input->displayName, input->layerId, input->userId);
|
state.logger->Debug("Opening Layer: Display Name: {}, Layer ID: {}, User ID: {}", input.displayName, input.layerId, input.userId);
|
||||||
std::string name(input->displayName);
|
std::string name(input.displayName);
|
||||||
gpu::Parcel parcel(state);
|
gpu::Parcel parcel(state);
|
||||||
LayerParcel data{
|
LayerParcel data{
|
||||||
.type = 0x20,
|
.type = 0x20,
|
||||||
@ -86,24 +86,22 @@ namespace skyline::service::vi {
|
|||||||
};
|
};
|
||||||
parcel.WriteData(data);
|
parcel.WriteData(data);
|
||||||
parcel.objects.resize(4);
|
parcel.objects.resize(4);
|
||||||
response.WriteValue(parcel.WriteParcel(request.vecBufB[0]));
|
response.Push(parcel.WriteParcel(request.outputBuf.at(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationDisplayService::CloseLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IApplicationDisplayService::CloseLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
u64 layerId = *reinterpret_cast<u64 *>(request.cmdArg);
|
u64 layerId = request.Pop<u64>();
|
||||||
state.logger->Debug("Closing Layer: {}", layerId);
|
state.logger->Debug("Closing Layer: {}", layerId);
|
||||||
if (state.gpu->layerStatus == gpu::LayerStatus::Uninitialized)
|
if (state.gpu->layerStatus == gpu::LayerStatus::Uninitialized)
|
||||||
state.logger->Warn("The application is destroying an uninitialized layer");
|
state.logger->Warn("The application is destroying an uninitialized layer");
|
||||||
state.gpu->layerStatus = gpu::LayerStatus::Uninitialized;
|
state.gpu->layerStatus = gpu::LayerStatus::Uninitialized;
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationDisplayService::SetLayerScalingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IApplicationDisplayService::SetLayerScalingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
auto scalingMode = request.Pop<u64>();
|
||||||
u64 scalingMode;
|
auto layerId = request.Pop<u64>();
|
||||||
u64 layerId;
|
state.logger->Debug("Setting Layer Scaling mode to '{}' for layer {}", scalingMode, layerId);
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
state.logger->Debug("Setting Layer Scaling mode to '{}' for layer {}", input->scalingMode, input->layerId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationDisplayService::GetDisplayVsyncEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IApplicationDisplayService::GetDisplayVsyncEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
@ -118,7 +116,7 @@ namespace skyline::service::vi {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void ISystemDisplayService::SetLayerZ(skyline::kernel::type::KSession &session, skyline::kernel::ipc::IpcRequest &request, skyline::kernel::ipc::IpcResponse &response) {
|
void ISystemDisplayService::SetLayerZ(skyline::kernel::type::KSession &session, skyline::kernel::ipc::IpcRequest &request, skyline::kernel::ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
IManagerDisplayService::IManagerDisplayService(const DeviceState &state, ServiceManager &manager) : IDisplayService(state, manager, Service::vi_IManagerDisplayService, {
|
IManagerDisplayService::IManagerDisplayService(const DeviceState &state, ServiceManager &manager) : IDisplayService(state, manager, Service::vi_IManagerDisplayService, {
|
||||||
@ -129,16 +127,13 @@ namespace skyline::service::vi {
|
|||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
void IManagerDisplayService::CreateManagedLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IManagerDisplayService::CreateManagedLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
struct InputStruct {
|
request.Skip<u32>();
|
||||||
u32 _unk0_;
|
u64 displayId = request.Pop<u64>();
|
||||||
u64 displayId;
|
state.logger->Debug("Creating Managed Layer: {}", displayId);
|
||||||
u64 userId;
|
|
||||||
} *input = reinterpret_cast<InputStruct *>(request.cmdArg);
|
|
||||||
state.logger->Debug("Creating Managed Layer: {}", input->displayId);
|
|
||||||
if (state.gpu->layerStatus == gpu::LayerStatus::Initialized)
|
if (state.gpu->layerStatus == gpu::LayerStatus::Initialized)
|
||||||
throw exception("The application is creating more than one layer");
|
throw exception("The application is creating more than one layer");
|
||||||
state.gpu->layerStatus = gpu::LayerStatus::Initialized;
|
state.gpu->layerStatus = gpu::LayerStatus::Initialized;
|
||||||
response.WriteValue<u64>(0); // There's only one layer
|
response.Push<u64>(0); // There's only one layer
|
||||||
}
|
}
|
||||||
|
|
||||||
void IManagerDisplayService::DestroyManagedLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IManagerDisplayService::DestroyManagedLayer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
@ -146,10 +141,10 @@ namespace skyline::service::vi {
|
|||||||
if (state.gpu->layerStatus == gpu::LayerStatus::Uninitialized)
|
if (state.gpu->layerStatus == gpu::LayerStatus::Uninitialized)
|
||||||
state.logger->Warn("The application is destroying an uninitialized layer");
|
state.logger->Warn("The application is destroying an uninitialized layer");
|
||||||
state.gpu->layerStatus = gpu::LayerStatus::Uninitialized;
|
state.gpu->layerStatus = gpu::LayerStatus::Uninitialized;
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IManagerDisplayService::AddToLayerStack(skyline::kernel::type::KSession &session, skyline::kernel::ipc::IpcRequest &request, skyline::kernel::ipc::IpcResponse &response) {
|
void IManagerDisplayService::AddToLayerStack(skyline::kernel::type::KSession &session, skyline::kernel::ipc::IpcRequest &request, skyline::kernel::ipc::IpcResponse &response) {
|
||||||
response.WriteValue<u32>(constant::status::Success);
|
response.Push<u32>(constant::status::Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user