nim-libnx/src/libnx_wrapper/ipc.nim
Joey Yakimowich-Payne 54d10731d3 Rename wrappers for now
2018-06-22 16:19:15 +09:00

341 lines
14 KiB
Nim

import strutils
import ospaths
const headeripc = currentSourcePath().splitPath().head & "/nx/include/switch/kernel/ipc.h"
## *
## @file ipc.h
## @brief Inter-process communication handling
## @author plutoo
## @copyright libnx Authors
##
import
libnx_wrapper/types,
libnx_wrapper/result, libnx_wrapper/tls, libnx_wrapper/svc
## / IPC input header magic
const
SFCI_MAGIC* = 0x49434653
## / IPC output header magic
const
SFCO_MAGIC* = 0x4F434653
## / IPC invalid object ID
const
IPC_INVALID_OBJECT_ID* = uint32.high
## /@name IPC request building
## /@{
## / IPC command (request) structure.
const
IPC_MAX_BUFFERS* = 8
IPC_MAX_OBJECTS* = 8
type
BufferType* {.size: sizeof(cint).} = enum
BufferType_Normal = 0, ## /< Regular buffer.
BufferType_Type1 = 1, ## /< Allows ProcessMemory and shared TransferMemory.
BufferType_Invalid = 2, BufferType_Type3 = 3
BufferDirection* {.size: sizeof(cint).} = enum
BufferDirection_Send = 0, BufferDirection_Recv = 1, BufferDirection_Exch = 2
IpcCommandType* {.size: sizeof(cint).} = enum
IpcCommandType_Invalid = 0, IpcCommandType_LegacyRequest = 1,
IpcCommandType_Close = 2, IpcCommandType_LegacyControl = 3,
IpcCommandType_Request = 4, IpcCommandType_Control = 5,
IpcCommandType_RequestWithContext = 6, IpcCommandType_ControlWithContext = 7
IpcCommand* {.importc: "IpcCommand", header: headeripc, bycopy.} = object
NumSend* {.importc: "NumSend".}: csize ## A
NumRecv* {.importc: "NumRecv".}: csize ## B
NumExch* {.importc: "NumExch".}: csize ## W
Buffers* {.importc: "Buffers".}: array[IPC_MAX_BUFFERS, pointer]
BufferSizes* {.importc: "BufferSizes".}: array[IPC_MAX_BUFFERS, csize]
BufferTypes* {.importc: "BufferTypes".}: array[IPC_MAX_BUFFERS, BufferType]
NumStaticIn* {.importc: "NumStaticIn".}: csize ## X
NumStaticOut* {.importc: "NumStaticOut".}: csize ## C
Statics* {.importc: "Statics".}: array[IPC_MAX_BUFFERS, pointer]
StaticSizes* {.importc: "StaticSizes".}: array[IPC_MAX_BUFFERS, csize]
StaticIndices* {.importc: "StaticIndices".}: array[IPC_MAX_BUFFERS, uint8]
SendPid* {.importc: "SendPid".}: bool
NumHandlesCopy* {.importc: "NumHandlesCopy".}: csize
NumHandlesMove* {.importc: "NumHandlesMove".}: csize
Handles* {.importc: "Handles".}: array[IPC_MAX_OBJECTS, Handle]
NumObjectIds* {.importc: "NumObjectIds".}: csize
ObjectIds* {.importc: "ObjectIds".}: array[IPC_MAX_OBJECTS, uint32]
## *
## @brief Initializes an IPC command structure.
## @param cmd IPC command structure.
##
proc ipcInitialize*(cmd: ptr IpcCommand) {.inline, cdecl, importc: "ipcInitialize",
header: headeripc.}
## / IPC buffer descriptor.
type
IpcBufferDescriptor* {.importc: "IpcBufferDescriptor", header: headeripc, bycopy.} = object
Size* {.importc: "Size".}: uint32 ## /< Size of the buffer.
Addr* {.importc: "Addr".}: uint32 ## /< Lower 32-bits of the address of the buffer
Packed* {.importc: "Packed".}: uint32 ## /< Packed data (including higher bits of the address)
## / IPC static send-buffer descriptor.
type
IpcStaticSendDescriptor* {.importc: "IpcStaticSendDescriptor", header: headeripc,
bycopy.} = object
Packed* {.importc: "Packed".}: uint32 ## /< Packed data (including higher bits of the address)
Addr* {.importc: "Addr".}: uint32 ## /< Lower 32-bits of the address
## / IPC static receive-buffer descriptor.
type
IpcStaticRecvDescriptor* {.importc: "IpcStaticRecvDescriptor", header: headeripc,
bycopy.} = object
Addr* {.importc: "Addr".}: uint32 ## /< Lower 32-bits of the address of the buffer
Packed* {.importc: "Packed".}: uint32 ## /< Packed data (including higher bits of the address)
## *
## @brief Adds a buffer to an IPC command structure.
## @param cmd IPC command structure.
## @param buffer Address of the buffer.
## @param size Size of the buffer.
## @param type Buffer type.
##
proc ipcAddSendBuffer*(cmd: ptr IpcCommand; buffer: pointer; size: csize;
`type`: BufferType) {.inline, cdecl,
importc: "ipcAddSendBuffer", header: headeripc.}
## *
## @brief Adds a receive-buffer to an IPC command structure.
## @param cmd IPC command structure.
## @param buffer Address of the buffer.
## @param size Size of the buffer.
## @param type Buffer type.
##
proc ipcAddRecvBuffer*(cmd: ptr IpcCommand; buffer: pointer; size: csize;
`type`: BufferType) {.inline, cdecl,
importc: "ipcAddRecvBuffer", header: headeripc.}
## *
## @brief Adds an exchange-buffer to an IPC command structure.
## @param cmd IPC command structure.
## @param buffer Address of the buffer.
## @param size Size of the buffer.
## @param type Buffer type.
##
proc ipcAddExchBuffer*(cmd: ptr IpcCommand; buffer: pointer; size: csize;
`type`: BufferType) {.inline, cdecl,
importc: "ipcAddExchBuffer", header: headeripc.}
## *
## @brief Adds a static-buffer to an IPC command structure.
## @param cmd IPC command structure.
## @param buffer Address of the buffer.
## @param size Size of the buffer.
## @param index Index of buffer.
##
proc ipcAddSendStatic*(cmd: ptr IpcCommand; buffer: pointer; size: csize; index: uint8) {.
inline, cdecl, importc: "ipcAddSendStatic", header: headeripc.}
## *
## @brief Adds a static-receive-buffer to an IPC command structure.
## @param cmd IPC command structure.
## @param buffer Address of the buffer.
## @param size Size of the buffer.
## @param index Index of buffer.
##
proc ipcAddRecvStatic*(cmd: ptr IpcCommand; buffer: pointer; size: csize; index: uint8) {.
inline, cdecl, importc: "ipcAddRecvStatic", header: headeripc.}
## *
## @brief Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure.
## @param cmd IPC command structure.
## @param ipc_buffer_size IPC buffer size.
## @param buffer Address of the buffer.
## @param size Size of the buffer.
## @param index Index of buffer.
##
proc ipcAddSendSmart*(cmd: ptr IpcCommand; ipc_buffer_size: csize; buffer: pointer;
size: csize; index: uint8) {.inline, cdecl,
importc: "ipcAddSendSmart", header: headeripc.}
## *
## @brief Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure.
## @param cmd IPC command structure.
## @param ipc_buffer_size IPC buffer size.
## @param buffer Address of the buffer.
## @param size Size of the buffer.
## @param index Index of buffer.
##
proc ipcAddRecvSmart*(cmd: ptr IpcCommand; ipc_buffer_size: csize; buffer: pointer;
size: csize; index: uint8) {.inline, cdecl,
importc: "ipcAddRecvSmart", header: headeripc.}
## *
## @brief Tags an IPC command structure to send the PID.
## @param cmd IPC command structure.
##
proc ipcSendPid*(cmd: ptr IpcCommand) {.inline, cdecl, importc: "ipcSendPid",
header: headeripc.}
## *
## @brief Adds a copy-handle to be sent through an IPC command structure.
## @param cmd IPC command structure.
## @param h Handle to send.
## @remark The receiving process gets a copy of the handle.
##
proc ipcSendHandleCopy*(cmd: ptr IpcCommand; h: Handle) {.inline, cdecl,
importc: "ipcSendHandleCopy", header: headeripc.}
## *
## @brief Adds a move-handle to be sent through an IPC command structure.
## @param cmd IPC command structure.
## @param h Handle to send.
## @remark The sending process loses ownership of the handle, which is transferred to the receiving process.
##
proc ipcSendHandleMove*(cmd: ptr IpcCommand; h: Handle) {.inline, cdecl,
importc: "ipcSendHandleMove", header: headeripc.}
## *
## @brief Prepares the header of an IPC command structure.
## @param cmd IPC command structure.
## @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request
## @return Pointer to the raw embedded data structure in the request, ready to be filled out.
##
proc ipcPrepareHeader*(cmd: ptr IpcCommand; sizeof_raw: csize): pointer {.inline,
cdecl, importc: "ipcPrepareHeader", header: headeripc.}
## *
## @brief Dispatches an IPC request.
## @param session IPC session handle.
## @return Result code.
##
proc ipcDispatch*(session: Handle): Result {.inline, cdecl, importc: "ipcDispatch",
header: headeripc.}
## /@}
## /@name IPC response parsing
## /@{
## / IPC parsed command (response) structure.
type
IpcParsedCommand* {.importc: "IpcParsedCommand", header: headeripc, bycopy.} = object
CommandType* {.importc: "CommandType".}: IpcCommandType ## /< Type of the command
HasPid* {.importc: "HasPid".}: bool ## /< true if the 'Pid' field is filled out.
Pid* {.importc: "Pid".}: uint64 ## /< PID included in the response (only if HasPid is true)
NumHandles* {.importc: "NumHandles".}: csize ## /< Number of handles copied.
Handles* {.importc: "Handles".}: array[IPC_MAX_OBJECTS, Handle] ## /< Handles.
WasHandleCopied* {.importc: "WasHandleCopied".}: array[IPC_MAX_OBJECTS, bool] ## /< true if the handle was moved, false if it was copied.
ThisObjectId* {.importc: "ThisObjectId".}: uint32 ## /< Object ID to call the command on (for domain messages).
NumObjectIds* {.importc: "NumObjectIds".}: csize ## /< Number of object IDs (for domain messages).
ObjectIds* {.importc: "ObjectIds".}: array[IPC_MAX_OBJECTS, uint32] ## /< Object IDs (for domain messages).
NumBuffers* {.importc: "NumBuffers".}: csize ## /< Number of buffers in the response.
Buffers* {.importc: "Buffers".}: array[IPC_MAX_BUFFERS, pointer] ## /< Pointers to the buffers.
BufferSizes* {.importc: "BufferSizes".}: array[IPC_MAX_BUFFERS, csize] ## /< Sizes of the buffers.
BufferTypes* {.importc: "BufferTypes".}: array[IPC_MAX_BUFFERS, BufferType] ## /< Types of the buffers.
BufferDirections* {.importc: "BufferDirections".}: array[IPC_MAX_BUFFERS,
BufferDirection] ## /< Direction of each buffer.
NumStatics* {.importc: "NumStatics".}: csize ## /< Number of statics in the response.
Statics* {.importc: "Statics".}: array[IPC_MAX_BUFFERS, pointer] ## /< Pointers to the statics.
StaticSizes* {.importc: "StaticSizes".}: array[IPC_MAX_BUFFERS, csize] ## /< Sizes of the statics.
StaticIndices* {.importc: "StaticIndices".}: array[IPC_MAX_BUFFERS, uint8] ## /< Indices of the statics.
NumStaticsOut* {.importc: "NumStaticsOut".}: csize ## /< Number of output statics available in the response.
Raw* {.importc: "Raw".}: pointer ## /< Pointer to the raw embedded data structure in the response.
RawWithoutPadding* {.importc: "RawWithoutPadding".}: pointer ## /< Pointer to the raw embedded data structure, without padding.
RawSize* {.importc: "RawSize".}: csize ## /< Size of the raw embedded data.
## *
## @brief Parse an IPC command response into an IPC parsed command structure.
## @param IPC parsed command structure to fill in.
## @return Result code.
##
proc ipcParse*(r: ptr IpcParsedCommand): Result {.inline, cdecl, importc: "ipcParse",
header: headeripc.}
## *
## @brief Queries the size of an IPC pointer buffer.
## @param session IPC session handle.
## @param size Output variable in which to store the size.
## @return Result code.
##
proc ipcQueryPointerBufferSize*(session: Handle; size: ptr csize): Result {.inline,
cdecl, importc: "ipcQueryPointerBufferSize", header: headeripc.}
## *
## @brief Closes the IPC session with proper clean up.
## @param session IPC session handle.
## @return Result code.
##
proc ipcCloseSession*(session: Handle): Result {.inline, cdecl,
importc: "ipcCloseSession", header: headeripc.}
## /@}
## /@name IPC domain handling
## /@{
## *
## @brief Converts an IPC session handle into a domain.
## @param session IPC session handle.
## @param object_id_out Output variable in which to store the object ID.
## @return Result code.
##
proc ipcConvertSessionToDomain*(session: Handle; object_id_out: ptr uint32): Result {.
inline, cdecl, importc: "ipcConvertSessionToDomain", header: headeripc.}
## *
## @brief Adds an object ID to be sent through an IPC domain command structure.
## @param cmd IPC domain command structure.
## @param object_id Object ID to send.
##
proc ipcSendObjectId*(cmd: ptr IpcCommand; object_id: uint32) {.inline, cdecl,
importc: "ipcSendObjectId", header: headeripc.}
## / IPC domain message header.
type
DomainMessageHeader* {.importc: "DomainMessageHeader", header: headeripc, bycopy.} = object
Type* {.importc: "Type".}: uint8
NumObjectIds* {.importc: "NumObjectIds".}: uint8
Length* {.importc: "Length".}: uint16
ThisObjectId* {.importc: "ThisObjectId".}: uint32
Pad* {.importc: "Pad".}: array[2, uint32]
## *
## @brief Prepares the header of an IPC command structure (domain version).
## @param cmd IPC command structure.
## @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request
## @oaram object_id Domain object ID.
## @return Pointer to the raw embedded data structure in the request, ready to be filled out.
##
proc ipcPrepareHeaderForDomain*(cmd: ptr IpcCommand; sizeof_raw: csize; object_id: uint32): pointer {.
inline, cdecl, importc: "ipcPrepareHeaderForDomain", header: headeripc.}
## *
## @brief Parse an IPC command response into an IPC parsed command structure (domain version).
## @param IPC parsed command structure to fill in.
## @return Result code.
##
proc ipcParseForDomain*(r: ptr IpcParsedCommand): Result {.inline, cdecl,
importc: "ipcParseForDomain", header: headeripc.}
## *
## @brief Closes a domain object by ID.
## @param session IPC session handle.
## @param object_id ID of the object to close.
## @return Result code.
##
proc ipcCloseObjectById*(session: Handle; object_id: uint32): Result {.inline, cdecl,
importc: "ipcCloseObjectById", header: headeripc.}
## /@}